@ai-matrx/alchemy 0.11.0 → 0.12.0

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +1 -1
  3. package/dist/actions.cjs +1 -1
  4. package/dist/actions.cjs.map +1 -1
  5. package/dist/actions.d.cts +72 -1
  6. package/dist/actions.d.ts +72 -1
  7. package/dist/actions.js +1 -1
  8. package/dist/actions.js.map +1 -1
  9. package/dist/checks.cjs +1 -1
  10. package/dist/checks.cjs.map +1 -1
  11. package/dist/checks.d.cts +8 -0
  12. package/dist/checks.d.ts +8 -0
  13. package/dist/checks.js +1 -1
  14. package/dist/checks.js.map +1 -1
  15. package/dist/core.d.cts +8 -0
  16. package/dist/core.d.ts +8 -0
  17. package/dist/declare/schema.json +3 -0
  18. package/dist/declare.d.cts +8 -0
  19. package/dist/declare.d.ts +8 -0
  20. package/dist/index.d.cts +8 -0
  21. package/dist/index.d.ts +8 -0
  22. package/dist/menu.d.cts +29 -0
  23. package/dist/menu.d.ts +29 -0
  24. package/dist/operate.d.cts +8 -0
  25. package/dist/operate.d.ts +8 -0
  26. package/dist/ports.d.cts +8 -0
  27. package/dist/ports.d.ts +8 -0
  28. package/dist/react-bar.cjs +1 -1
  29. package/dist/react-bar.cjs.map +1 -1
  30. package/dist/react-bar.d.cts +8 -0
  31. package/dist/react-bar.d.ts +8 -0
  32. package/dist/react-bar.js +1 -1
  33. package/dist/react-bar.js.map +1 -1
  34. package/dist/react-host.cjs +1 -1
  35. package/dist/react-host.cjs.map +1 -1
  36. package/dist/react-host.d.cts +42 -1
  37. package/dist/react-host.d.ts +42 -1
  38. package/dist/react-host.js +1 -1
  39. package/dist/react-host.js.map +1 -1
  40. package/dist/react-menu.cjs +1 -1
  41. package/dist/react-menu.cjs.map +1 -1
  42. package/dist/react-menu.d.cts +8 -0
  43. package/dist/react-menu.d.ts +8 -0
  44. package/dist/react-menu.js +1 -1
  45. package/dist/react-menu.js.map +1 -1
  46. package/dist/react-overflow.cjs +1 -1
  47. package/dist/react-overflow.cjs.map +1 -1
  48. package/dist/react-overflow.d.cts +29 -0
  49. package/dist/react-overflow.d.ts +29 -0
  50. package/dist/react-overflow.js +1 -1
  51. package/dist/react-overflow.js.map +1 -1
  52. package/dist/react-palette.cjs +1 -1
  53. package/dist/react-palette.cjs.map +1 -1
  54. package/dist/react-palette.d.cts +8 -0
  55. package/dist/react-palette.d.ts +8 -0
  56. package/dist/react-palette.js +1 -1
  57. package/dist/react-palette.js.map +1 -1
  58. package/dist/react-selection.cjs +1 -1
  59. package/dist/react-selection.cjs.map +1 -1
  60. package/dist/react-selection.d.cts +8 -0
  61. package/dist/react-selection.d.ts +8 -0
  62. package/dist/react-selection.js +1 -1
  63. package/dist/react-selection.js.map +1 -1
  64. package/dist/react-sheet.cjs +1 -1
  65. package/dist/react-sheet.cjs.map +1 -1
  66. package/dist/react-sheet.d.cts +8 -0
  67. package/dist/react-sheet.d.ts +8 -0
  68. package/dist/react-sheet.js +1 -1
  69. package/dist/react-sheet.js.map +1 -1
  70. package/dist/surface.cjs +1 -1
  71. package/dist/surface.cjs.map +1 -1
  72. package/dist/surface.d.cts +12 -3
  73. package/dist/surface.d.ts +12 -3
  74. package/dist/surface.js +1 -1
  75. package/dist/surface.js.map +1 -1
  76. package/package.json +3 -3
package/dist/actions.d.ts CHANGED
@@ -121,6 +121,14 @@ interface SurfaceDeclaration {
121
121
  urlPattern?: string;
122
122
  inheritsFrom?: string;
123
123
  intro?: string;
124
+ /**
125
+ * The moment in plain words (`ui_surface.situation`, AP-6): a short paragraph
126
+ * with blanks `{value}`, `{value.path}` or `{value|words when missing}` bound to
127
+ * this surface's declared values and the request's `user`. The server renders
128
+ * it on every agent turn and puts it FIRST (`<situation>`). Omitted: the server
129
+ * builds an automatic sentence from the value labels.
130
+ */
131
+ situation?: string;
124
132
  overlayId?: string;
125
133
  values: readonly DeclaredValue[];
126
134
  groups?: readonly ValueGroup[];
@@ -981,9 +989,25 @@ interface ActionSection {
981
989
  */
982
990
  kind?: "group" | "target";
983
991
  }
992
+ /**
993
+ * Where an Action can be reached. "menu" (the default): menus, bars, palettes and sheets — it runs
994
+ * through `run(target, ctx)`. "invoke": code runs it BY ID through `invokeAction` — it runs through
995
+ * `invoke(input, ctx)`. An Action whose `surfaces` omits "menu" is never resolved into a menu, so it
996
+ * needs no eligibility of its own (`invocableAction` builds one).
997
+ */
998
+ type ActionSurface = "menu" | "invoke";
999
+ /** What a programmatic invocation receives: the host's ports and a capability-scoped context the caller binds. */
1000
+ interface InvocationContext {
1001
+ ports: AlchemyHostPorts;
1002
+ /** Opaque to the package: the capabilities the caller hands this one Action (a launcher, the acting user). */
1003
+ context: unknown;
1004
+ signal: AbortSignal;
1005
+ }
984
1006
  interface Action {
985
1007
  /** Globally unique. A duplicate is refused (never overwritten). */
986
1008
  id: string;
1009
+ /** Where it is reachable. Default ["menu"]. ["invoke"] = programmatic only: absent from every menu. */
1010
+ surfaces?: readonly ActionSurface[];
987
1011
  /** The provider that registered it — filled by the registry. */
988
1012
  provider?: string;
989
1013
  /** Resolved through I18nPort.t(labelKey ?? id, label). */
@@ -1043,6 +1067,11 @@ interface Action {
1043
1067
  /** Shown centred when `expand` resolves empty. */
1044
1068
  emptyLabel?: string;
1045
1069
  run(target: ClickTarget, context: ActionRunContext): Promise<TransferOutcome | void> | TransferOutcome | void;
1070
+ /**
1071
+ * The typed invocation channel (programmatic Actions): input in, a never-thrown result envelope out.
1072
+ * Called only by `invokeAction`; a throw here is captured there and answered `action_failed`.
1073
+ */
1074
+ invoke?(input: unknown, context: InvocationContext): Promise<ActionResult<unknown>> | ActionResult<unknown>;
1046
1075
  }
1047
1076
  /** One removed read, recorded (kit content-transfer's omission shape). */
1048
1077
  interface ReadOmission {
@@ -1104,6 +1133,12 @@ interface ActionRegistry {
1104
1133
  resolve(target: ClickTarget, restrict?: ResolveRestriction): Promise<readonly ResolvedAction[]>;
1105
1134
  /** Registered provider ids, in registration order. */
1106
1135
  providers(): readonly string[];
1136
+ /**
1137
+ * One Action by id, menu-reachable or not, or null. Asks only the provider that declared the id
1138
+ * (`declaredIds`); falls back to every provider when no declaration names it. Never throws: a
1139
+ * provider that throws is captured and skipped. `target` defaults to an empty click target.
1140
+ */
1141
+ get(id: string, target?: ClickTarget): Promise<Action | null>;
1107
1142
  /** Change notification (a provider registered or unregistered). */
1108
1143
  subscribe(listener: () => void): () => void;
1109
1144
  }
@@ -1145,6 +1180,8 @@ declare function computeEligibility(action: Action, target: ClickTarget, options
1145
1180
  status: "contract-break";
1146
1181
  reason: string;
1147
1182
  };
1183
+ /** True unless the Action declares `surfaces` without "menu" (default: a menu Action). */
1184
+ declare function isMenuAction(action: Pick<Action, "surfaces">): boolean;
1148
1185
  declare function createActionRegistry(options: ActionRegistryOptions): ActionRegistry;
1149
1186
  /** A provider over a fixed list; its ids are declared up front so duplicates fail at registration. */
1150
1187
  declare function staticActionProvider(id: string, actions: readonly Action[], tier?: ActionProvider["tier"]): ActionProvider;
@@ -1235,6 +1272,40 @@ type RunResult = {
1235
1272
  };
1236
1273
  declare function runAction(action: Action, target: ClickTarget, options: RunActionOptions): Promise<RunResult>;
1237
1274
 
1275
+ /**
1276
+ * The one programmatic runner. Menu Actions run through `runAction(action, target)`; code that
1277
+ * names an Action BY ID (a kind component's `runAction(key, input)`, an accepted assist chip)
1278
+ * runs it here, on the same registry. It never throws: every outcome is an `ActionResult`.
1279
+ *
1280
+ * Refusals, by code:
1281
+ * - `not_registered` — no provider yields that id.
1282
+ * - `not_invocable` — the Action exists but has no `invoke` channel (a menu-only Action).
1283
+ * - `lookup_failed` — the registry itself threw while finding it (captured).
1284
+ * - `action_failed` — `invoke` threw or answered something that is not an envelope (captured + announced once
1285
+ * through `notify.error`; the caller never announces it again).
1286
+ */
1287
+
1288
+ interface InvokeActionOptions {
1289
+ ports: AlchemyHostPorts;
1290
+ /** The capability-scoped context this one Action receives (opaque to the package). */
1291
+ context?: unknown;
1292
+ signal?: AbortSignal;
1293
+ }
1294
+ declare function invokeAction<T = unknown>(registry: Pick<ActionRegistry, "get">, id: string, input: unknown, options: InvokeActionOptions): Promise<ActionResult<T>>;
1295
+ interface InvocableActionDefinition {
1296
+ /** Globally unique; namespace it (`kind.trigger_agent`). */
1297
+ id: string;
1298
+ label: string;
1299
+ description?: string;
1300
+ category?: Action["category"];
1301
+ invoke: NonNullable<Action["invoke"]>;
1302
+ }
1303
+ /**
1304
+ * A programmatic-only Action: `surfaces: ["invoke"]`, so no menu ever resolves it; `run` refuses
1305
+ * (only `invokeAction` reaches it). Register it like any Action, on the one registry.
1306
+ */
1307
+ declare function invocableAction(def: InvocableActionDefinition): Action;
1308
+
1238
1309
  /** Default `category` of an Action that names none. */
1239
1310
  declare const APPLET_CATEGORY = "applet";
1240
1311
  /** The DB default of `ui.ui_surface_action.triggered_by`, used where a source carries no list. */
@@ -1354,4 +1425,4 @@ declare function fillActionTarget(template: string, input: unknown): {
1354
1425
  declare function refuseCaller(info: Pick<ActionInfo, "name" | "label" | "policy" | "triggeredBy">, by: ActionCaller): ActionError | null;
1355
1426
  declare function runSurfaceAction(info: ActionInfo, input: unknown, by: ActionCaller, ports: SurfaceActionPorts, options?: RunSurfaceActionOptions): Promise<ActionResult<unknown>>;
1356
1427
 
1357
- export { ACTION_CALLERS, ACTION_CATEGORIES, ACTION_POLICIES, ACTION_RUNS, APPLET_CATEGORY, type Action, type ActionCaller, type ActionCategory, type ActionChainLink, type ActionContext, type ActionDeclaration, type ActionDeclaredBy, type ActionError, type ActionInfo, type ActionInput, type ActionOrigin, type ActionPolicy, type ActionProvider, type ActionRegistry, type ActionRegistryOptions, type ActionResult, type ActionRunContext, type ActionRuns, type ActionSection, type ActionWriteMode, type ClickTarget, type ClickTargetInput, type ClientToolRow, DEFAULT_TRIGGERED_BY, DuplicateActionError, DuplicateProviderError, type Eligibility, type MandateRunRef, type MandateRunRequest, type ProjectedReads, type ProjectionSource, type ReadOmission, type ResolveRestriction, type ResolvedAction, type RunActionOptions, type RunResult, type RunSurfaceActionOptions, type ServerActionRunRequest, type ServerActionRunResponse, type SurfaceActionPorts, type SurfaceActionRow, type SurfacePort, UNIVERSAL_VERBS, type UniversalVerb, alwaysEligible, clientToolToAction, computeEligibility, createActionRegistry, createClickTarget, createProjectedReads, fillActionTarget, projectValues, refuseCaller, resolveActionChain, runAction, runSurfaceAction, staticActionProvider, surfaceActionRowToAction, toActionInfo, writeTargetToAction };
1428
+ export { ACTION_CALLERS, ACTION_CATEGORIES, ACTION_POLICIES, ACTION_RUNS, APPLET_CATEGORY, type Action, type ActionCaller, type ActionCategory, type ActionChainLink, type ActionContext, type ActionDeclaration, type ActionDeclaredBy, type ActionError, type ActionInfo, type ActionInput, type ActionOrigin, type ActionPolicy, type ActionProvider, type ActionRegistry, type ActionRegistryOptions, type ActionResult, type ActionRunContext, type ActionRuns, type ActionSection, type ActionSurface, type ActionWriteMode, type ClickTarget, type ClickTargetInput, type ClientToolRow, DEFAULT_TRIGGERED_BY, DuplicateActionError, DuplicateProviderError, type Eligibility, type InvocableActionDefinition, type InvocationContext, type InvokeActionOptions, type MandateRunRef, type MandateRunRequest, type ProjectedReads, type ProjectionSource, type ReadOmission, type ResolveRestriction, type ResolvedAction, type RunActionOptions, type RunResult, type RunSurfaceActionOptions, type ServerActionRunRequest, type ServerActionRunResponse, type SurfaceActionPorts, type SurfaceActionRow, type SurfacePort, UNIVERSAL_VERBS, type UniversalVerb, alwaysEligible, clientToolToAction, computeEligibility, createActionRegistry, createClickTarget, createProjectedReads, fillActionTarget, invocableAction, invokeAction, isMenuAction, projectValues, refuseCaller, resolveActionChain, runAction, runSurfaceAction, staticActionProvider, surfaceActionRowToAction, toActionInfo, writeTargetToAction };
package/dist/actions.js CHANGED
@@ -1,2 +1,2 @@
1
- var UNIVERSAL_VERBS=["copy","cut","paste","undo","redo","find"];var ACTION_CATEGORIES=["feedback","copy","export","save","edit","share","creator","app","listen","study","ask","ai","admin","clipboard","history","surface-info","applet"];var DuplicateActionError=class extends Error{actionId;providers;constructor(actionId,first,second){super(first===second?`Action "${actionId}" is yielded twice by provider "${first}". Ids are unique; the second was refused.`:`Action "${actionId}" is registered by provider "${first}" and again by "${second}". Ids are unique; "${second}"'s copy was refused.`),this.name="DuplicateActionError",this.actionId=actionId,this.providers=[first,second]}},DuplicateProviderError=class extends Error{providerId;constructor(providerId){super(`Action provider "${providerId}" is already registered. Unregister it first; nothing was overwritten.`),this.name="DuplicateProviderError",this.providerId=providerId}},VERBS=new Set(UNIVERSAL_VERBS);function capture(ports,error,detail){try{ports.diagnostics.capture(error,{area:"actions",detail})}catch{}}function computeEligibility(action,target,options){let restrict=options.restrict;if(target.excludedActionIds.has(action.id))return{status:"absent"};if(restrict?.exclude?.includes(action.id))return{status:"absent"};if(restrict?.categories&&!restrict.categories.includes(action.category))return{status:"absent"};if(action.writes&&action.writes.length>0){if(target.readOnly)return{status:"absent"};let writable=new Set(target.writable.map(w=>w.name));if(!action.writes.some(name=>writable.has(name)))return{status:"absent"}}if(action.requiresAuth&&!target.auth.authenticated&&!options.authResumable)return{status:"absent"};let own=action.eligible(target);return own.status==="unavailable"?own.sentence.trim()?own:{status:"absent"}:own.status!=="unavailable-verb"?own:action.category!=="clipboard"||!VERBS.has(own.verb)?{status:"contract-break",reason:`Action "${action.id}" answered unavailable-verb but only the six universal verbs (category "clipboard") may grey; it is absent instead.`}:own.sentence.trim()?own:{status:"contract-break",reason:`Universal verb "${action.id}" greyed without a sentence; a greyed verb must say why.`}}function createActionRegistry(options){let ports=options.ports,entries=new Map,listeners=new Set,notify=()=>{for(let l of[...listeners])l()};return{register(provider){if(entries.has(provider.id))throw new DuplicateProviderError(provider.id);let declared=provider.declaredIds?.()??[],own=new Set;for(let id of declared){if(own.has(id))throw new DuplicateActionError(id,provider.id,provider.id);own.add(id);for(let[otherId,other]of entries)if(other.declared.includes(id))throw new DuplicateActionError(id,otherId,provider.id)}let entry={provider,declared};return entries.set(provider.id,entry),notify(),()=>{entries.get(provider.id)===entry&&(entries.delete(provider.id),notify())}},async resolve(target,restrict){let authResumable=!!ports.auth,seen=new Map,out=[];for(let[providerId,{provider}]of[...entries]){let actions;try{actions=await provider.actions(target)}catch(error){capture(ports,error,{providerId,stage:"actions"});continue}for(let raw of actions){let first=seen.get(raw.id);if(first!==void 0){capture(ports,new DuplicateActionError(raw.id,first,providerId),{actionId:raw.id});continue}seen.set(raw.id,providerId);let action=raw.provider===providerId?raw:{...raw,provider:providerId},eligibility;try{eligibility=computeEligibility(action,target,{restrict:restrict??{},authResumable})}catch(error){capture(ports,error,{actionId:action.id,stage:"eligible"});continue}if(eligibility.status==="contract-break"){capture(ports,new Error(eligibility.reason),{actionId:action.id,stage:"eligible"});continue}eligibility.status!=="absent"&&out.push({action,eligibility})}}return out},providers(){return[...entries.keys()]},subscribe(listener){return listeners.add(listener),()=>{listeners.delete(listener)}}}}function staticActionProvider(id,actions,tier="T0"){let list=actions.map(a=>a.provider===id?a:{...a,provider:id});return{id,tier,declaredIds:()=>list.map(a=>a.id),actions:()=>list}}var alwaysEligible=()=>({status:"available"});var DEFAULT_SENSITIVITY=Object.freeze({exportable:!0,classification:"ordinary",includedByDefault:!0});function resolveSensitivity(value){return{exportable:value.sensitivity?.exportable??DEFAULT_SENSITIVITY.exportable,classification:value.sensitivity?.classification??DEFAULT_SENSITIVITY.classification,includedByDefault:value.sensitivity?.includedByDefault??DEFAULT_SENSITIVITY.includedByDefault}}function toJson(value){if(!(value===void 0||typeof value=="function"||typeof value=="symbol")){if(value===null||typeof value=="string"||typeof value=="boolean")return value;if(typeof value=="number")return Number.isFinite(value)?value:null;if(typeof value=="bigint")return value.toString();if(value instanceof Date)return value.toISOString();if(Array.isArray(value))return value.map(v=>toJson(v)??null);if(typeof value=="object"){let out={};for(let[k,v]of Object.entries(value)){let j=toJson(v);j!==void 0&&(out[k]=j)}return out}}}function projectValues(raw,declared,pathPrefix=""){let byName=new Map(declared.map(d=>[d.name,d])),values={},omissions=[];for(let[name,value]of Object.entries(raw)){let path=pathPrefix?`${pathPrefix}.${name}`:name,decl=byName.get(name);if(!decl){omissions.push({path,reason:"filtered"});continue}let sensitivity=resolveSensitivity(decl);if(sensitivity.classification!=="ordinary"){omissions.push({path,reason:"excluded",classification:sensitivity.classification});continue}if(!sensitivity.exportable){omissions.push({path,reason:"excluded"});continue}let json=toJson(value);json!==void 0&&(values[name]=json)}return{values,omissions}}function createProjectedReads(source){return{async values(signal){if(!source.surface||!source.declaration)return{values:{},omissions:[]};let raw=await source.surface.readValues(signal),screenValues=source.declaration.values;return projectValues(raw,screenValues)},async item(signal){let item=source.item;if(!item||!source.declaration)return null;let type=source.declaration.itemTypes?.find(t=>t.name===item.itemType);if(!type)return{values:{},omissions:[{path:item.itemType,reason:"filtered"}]};let raw=await item.readValues(signal);return projectValues(raw,type.values,item.itemType)},async live(signal){return source.surface?.readLive?source.surface.readLive(signal):{}}}}function qualifyValueKey(itemType,name){return itemType?`${itemType}.${name}`:name}function domainOf(surfaceName){let slash=surfaceName.indexOf("/");return slash>0?surfaceName.slice(0,slash):surfaceName}function createClickTarget(input={}){let declaration=input.declaration??null,item=input.item??null,valueKeys=new Set,restricted=!1,writable=[];if(declaration){for(let value of declaration.values){valueKeys.add(value.name);let s=resolveSensitivity(value);(s.classification!=="ordinary"||!s.exportable)&&(restricted=!0)}let itemType=item?declaration.itemTypes?.find(t=>t.name===item.itemType):void 0;if(itemType){for(let value of itemType.values){valueKeys.add(qualifyValueKey(itemType.name,value.name));let s=resolveSensitivity(value);(s.classification!=="ordinary"||!s.exportable)&&(restricted=!0)}for(let t of itemType.writeTargets??[])writable.push(t)}for(let t of declaration.writeTargets??[])(!t.itemType||t.itemType===item?.itemType)&&writable.push(t)}let readOnly=input.readOnly??item?.readOnly??!1,surfaceName=input.surface?.surfaceName??declaration?.surfaceName??null,scopeChain=input.scopeChain??(surfaceName?["global",domainOf(surfaceName),surfaceName]:["global"]);return{surface:input.surface??null,declaration,valueKeys,scopeChain,excludedActionIds:new Set(input.excludedActionIds??[]),item,level:input.level??item?.level??null,selection:input.selection??null,payloadKinds:input.payloadKinds??[],writable:readOnly?[]:input.writable??writable,readOnly,restricted,organizationId:input.organizationId??null,auth:{authenticated:input.auth?.authenticated??!1,admin:input.auth?.admin??!1,creator:input.auth?.creator??!1},host:input.host}}async function runAction(action,target,options){let{ports}=options;if(action.requiresAuth&&!target.auth.authenticated)return ports.auth?(ports.auth.signInThenResume({actionId:action.id,contentFingerprint:options.contentFingerprint??action.id}),{status:"auth-pending"}):(ports.diagnostics.capture(new Error(`requiresAuth action "${action.id}" ran signed out with no auth port`),{area:"actions",detail:{actionId:action.id}}),{status:"failed",error:new Error("sign-in unavailable")});let reads=createProjectedReads(options.source??{surface:null,declaration:target.declaration,item:null}),signal=options.signal??new AbortController().signal;try{return{status:"ran",outcome:await action.run(target,{reads,ports,signal})}}catch(error){ports.diagnostics.capture(error,{area:"actions",detail:{actionId:action.id,stage:"run"}});let label=typeof action.label=="string"?action.label:action.id;return ports.notify?.error(`${label} did not finish.`,"Try again; if it keeps failing, report it from the feedback button."),{status:"failed",error}}}var DEFAULT_MAX_INHERITANCE_DEPTH=3;var APPLET_CATEGORY="applet",DEFAULT_TRIGGERED_BY=["person","agent","applet"],ACTION_CALLERS=["person","agent","applet","automation"],ACTION_RUNS=["page","server","mandate","navigate"],ACTION_POLICIES=["ask","auto","manual"];function compact(value){return Object.fromEntries(Object.entries(value).filter(([,v])=>v!==void 0))}var POLICY_OF_APPLY={manual:"manual",ask:"ask",auto:"auto",queued:"ask"};function writeTargetToAction(target){let applyPolicy=target.applyPolicy??"manual";return compact({name:target.name,label:target.label,description:target.description,input:target.valueKind??{jsonSchema:target.valueType==="document"?{}:{type:target.valueType}},runs:"page",triggeredBy:[...DEFAULT_TRIGGERED_BY],policy:POLICY_OF_APPLY[applyPolicy],updatesValue:target.updatesValue,mode:target.mode,patchable:target.patchable,approvalComparison:target.approvalComparison,streamOps:target.streamOps?[...target.streamOps]:void 0,destination:target.destination,groupKey:target.group,itemType:target.itemType,applyPolicy:target.applyPolicy,valueType:target.valueType,valueKind:target.valueKind,sortOrder:target.sortOrder,origin:{source:"write-target",declaredBy:"code"}})}function clientToolToAction(row){return compact({name:row.name,label:row.label,description:row.description,input:{jsonSchema:row.input_schema??{}},runs:"page",triggeredBy:["agent"],policy:row.mode==="draft"?"ask":"auto",mode:row.mode,origin:compact({source:"client-tool",surfaceName:row.surface_name,id:row.id,declaredBy:row.declared_by})})}function surfaceActionRowToAction(row){return compact({name:row.name,category:row.category,label:row.label,description:row.description,input:row.input??void 0,output:row.output??void 0,runs:row.runs,target:row.target??void 0,triggeredBy:[...row.triggered_by],policy:row.policy,updatesValue:row.updates_value??void 0,itemType:row.item_type||void 0,sortOrder:row.sort_order,origin:compact({source:"surface-action",surfaceName:row.surface_name,surfaceId:row.surface_id,id:row.id,declaredBy:row.declared_by,codeRef:row.code_ref??void 0,organizationId:row.organization_id??void 0})})}function toActionInfo(declaration,declaredOn){return compact({name:declaration.name,category:declaration.category??APPLET_CATEGORY,label:declaration.label,description:declaration.description,runs:declaration.runs,policy:declaration.policy,triggeredBy:[...declaration.triggeredBy],input:declaration.input,output:declaration.output,declaredOn,target:declaration.target,updatesValue:declaration.updatesValue,itemType:declaration.itemType,source:declaration.origin?.source})}function resolveActionChain(chain,options={}){let maxDepth=options.maxDepth??DEFAULT_MAX_INHERITANCE_DEPTH,names=chain.map(link=>link.surfaceName),seen=new Set;for(let name of names){if(seen.has(name))throw new Error(`[actions] inheritance CYCLE detected at "${name}". Fix the surface chain: ${names.join(" \u2192 ")}`);seen.add(name)}if(chain.length-1>maxDepth)throw new Error(`[actions] inheritance chain for "${names[names.length-1]}" exceeds depth ${maxDepth}: ${names.join(" \u2192 ")}`);let byName=new Map;for(let link of chain){let own=new Set;for(let action of link.actions){if(own.has(action.name))throw new Error(`[actions] surface "${link.surfaceName}" declares Action "${action.name}" twice. Names are unique; nothing was overwritten.`);own.add(action.name),byName.set(action.name,toActionInfo(action,link.surfaceName))}}return[...byName.values()]}function fail(code,message,retryable=!1,diagnostic){return{ok:!1,error:diagnostic?{code,message,retryable,diagnostic}:{code,message,retryable}}}function messageOf(error){return error instanceof Error&&error.message.trim()?error.message:typeof error=="string"&&error.trim()?error:"The run failed without saying why."}function newRunId(){let c=globalThis.crypto;return c?.randomUUID?c.randomUUID():`run-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function fillActionTarget(template,input){let source=input&&typeof input=="object"&&!Array.isArray(input)?input:{},missing=[];return{value:template.replace(/\{([A-Za-z_][A-Za-z0-9_]*)\}/g,(_,key)=>{let v=source[key];return v==null||v===""||typeof v=="object"?(missing.push(key),""):encodeURIComponent(String(v))}),missing}}function fillName(template,input){let filled=fillActionTarget(template,input);return{value:decodeURIComponent(filled.value),missing:filled.missing}}function toJson2(value){return value===void 0?null:JSON.parse(JSON.stringify(value))}function refuseCaller(info,by){return info.triggeredBy.includes(by)?info.policy==="manual"&&by!=="person"?{code:"manual_only",message:`"${info.label}" (${info.name}) runs only when a person starts it.`,retryable:!1}:null:{code:"caller_not_allowed",message:`"${info.label}" (${info.name}) can't be started by ${CALLER_WORDS[by]}; it allows ${info.triggeredBy.join(", ")||"no one"}.`,retryable:!1}}var CALLER_WORDS={person:"a person",agent:"an agent",applet:"an applet",automation:"an automation"};function absent(info,capability){return fail("capability_absent",`"${info.label}" can't run here: ${capability} isn't available on this page.`)}async function runSurfaceAction(info,input,by,ports,options={}){let refusal=refuseCaller(info,by);if(refusal)return{ok:!1,error:refusal};let context={runId:options.runId??newRunId(),by,viewerId:options.viewerId??null,surfaceName:info.declaredOn,policy:info.policy},capture2=(error,stage)=>{try{ports.diagnostics.capture(error,{area:"actions",detail:{action:info.name,runs:info.runs,stage,runId:context.runId}})}catch{}};try{if(info.source==="write-target"&&ports.door){let receipt=await ports.door.write({surfaceName:info.declaredOn,target:info.name,...info.itemType?{itemType:info.itemType}:{},...options.itemIdentity?{itemIdentity:options.itemIdentity}:{},...options.ops?{ops:options.ops}:{value:input},by,runId:context.runId},options.signal);return receipt.status==="refused"?{ok:!1,error:{code:receipt.reason,message:receipt.sentence,retryable:receipt.reason==="failed",remedy:receipt.remedy}}:{ok:!0,data:receipt}}if(info.policy==="ask"&&by!=="person"&&info.runs!=="server"){if(!ports.approvals)return fail("needs_approval",`"${info.label}" needs a person's approval, and there is no one to ask here.`);if(!await ports.approvals.ask({action:info.name,label:info.label,description:info.description,input:toJson2(input),by,surfaceName:info.declaredOn}))return fail("declined",`"${info.label}" was not approved, so it did not run.`)}switch(info.runs){case"server":{if(!ports.serverActions)return absent(info,"server actions");let filled=fillName(info.target??info.name,input);if(filled.missing.length)return fail("input_missing",`"${info.label}" needs ${filled.missing.join(", ")}.`);let response=await ports.serverActions.run({name:filled.value,input:toJson2(input),by,surface_name:info.declaredOn,policy:info.policy});return response.status==="refused"?fail("refused",response.message):{ok:!0,data:response}}case"mandate":{if(!ports.mandates)return absent(info,"running a job");if(!info.target)return fail("target_missing",`"${info.label}" names no job to run.`);let filled=fillName(info.target,input);if(filled.missing.length)return fail("input_missing",`"${info.label}" needs ${filled.missing.join(", ")}.`);let record=input&&typeof input=="object"&&!Array.isArray(input)?input:{},variables=/\{[A-Za-z_]/.test(info.target)?record.variables&&typeof record.variables=="object"?toJson2(record.variables):{}:toJson2(record),userInput=typeof record.userInput=="string"?record.userInput:void 0;return{ok:!0,data:await ports.mandates.run({alias:filled.value,variables,...userInput!==void 0?{userInput}:{},by,policy:info.policy})}}case"navigate":{if(!ports.overlay)return absent(info,"navigation");let filled=fillActionTarget(info.target??"",input);if(filled.missing.length)return fail("input_missing",`"${info.label}" needs ${filled.missing.join(", ")}.`);let to=info.target&&/^\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(info.target)?decodeURIComponent(filled.value):filled.value;return to?(ports.overlay.navigate(to),{ok:!0,data:{to}}):fail("target_missing",`"${info.label}" names no page to open.`)}case"page":return ports.pageActions?await ports.pageActions.dispatch(info.name,input,context):absent(info,"this page's actions");default:{let runs=info.runs;return fail("runs_unknown",`"${info.label}" runs as "${String(runs)}", which nothing here knows how to run.`)}}}catch(error){return capture2(error,"run"),fail("run_failed",messageOf(error),!0)}}export{ACTION_CALLERS,ACTION_CATEGORIES,ACTION_POLICIES,ACTION_RUNS,APPLET_CATEGORY,DEFAULT_TRIGGERED_BY,DuplicateActionError,DuplicateProviderError,UNIVERSAL_VERBS,alwaysEligible,clientToolToAction,computeEligibility,createActionRegistry,createClickTarget,createProjectedReads,fillActionTarget,projectValues,refuseCaller,resolveActionChain,runAction,runSurfaceAction,staticActionProvider,surfaceActionRowToAction,toActionInfo,writeTargetToAction};
1
+ var UNIVERSAL_VERBS=["copy","cut","paste","undo","redo","find"];var ACTION_CATEGORIES=["feedback","copy","export","save","edit","share","creator","app","listen","study","ask","ai","admin","clipboard","history","surface-info","applet"];var DEFAULT_SENSITIVITY=Object.freeze({exportable:!0,classification:"ordinary",includedByDefault:!0});function resolveSensitivity(value){return{exportable:value.sensitivity?.exportable??DEFAULT_SENSITIVITY.exportable,classification:value.sensitivity?.classification??DEFAULT_SENSITIVITY.classification,includedByDefault:value.sensitivity?.includedByDefault??DEFAULT_SENSITIVITY.includedByDefault}}function qualifyValueKey(itemType,name){return itemType?`${itemType}.${name}`:name}function domainOf(surfaceName){let slash=surfaceName.indexOf("/");return slash>0?surfaceName.slice(0,slash):surfaceName}function createClickTarget(input={}){let declaration=input.declaration??null,item=input.item??null,valueKeys=new Set,restricted=!1,writable=[];if(declaration){for(let value of declaration.values){valueKeys.add(value.name);let s=resolveSensitivity(value);(s.classification!=="ordinary"||!s.exportable)&&(restricted=!0)}let itemType=item?declaration.itemTypes?.find(t=>t.name===item.itemType):void 0;if(itemType){for(let value of itemType.values){valueKeys.add(qualifyValueKey(itemType.name,value.name));let s=resolveSensitivity(value);(s.classification!=="ordinary"||!s.exportable)&&(restricted=!0)}for(let t of itemType.writeTargets??[])writable.push(t)}for(let t of declaration.writeTargets??[])(!t.itemType||t.itemType===item?.itemType)&&writable.push(t)}let readOnly=input.readOnly??item?.readOnly??!1,surfaceName=input.surface?.surfaceName??declaration?.surfaceName??null,scopeChain=input.scopeChain??(surfaceName?["global",domainOf(surfaceName),surfaceName]:["global"]);return{surface:input.surface??null,declaration,valueKeys,scopeChain,excludedActionIds:new Set(input.excludedActionIds??[]),item,level:input.level??item?.level??null,selection:input.selection??null,payloadKinds:input.payloadKinds??[],writable:readOnly?[]:input.writable??writable,readOnly,restricted,organizationId:input.organizationId??null,auth:{authenticated:input.auth?.authenticated??!1,admin:input.auth?.admin??!1,creator:input.auth?.creator??!1},host:input.host}}var DuplicateActionError=class extends Error{actionId;providers;constructor(actionId,first,second){super(first===second?`Action "${actionId}" is yielded twice by provider "${first}". Ids are unique; the second was refused.`:`Action "${actionId}" is registered by provider "${first}" and again by "${second}". Ids are unique; "${second}"'s copy was refused.`),this.name="DuplicateActionError",this.actionId=actionId,this.providers=[first,second]}},DuplicateProviderError=class extends Error{providerId;constructor(providerId){super(`Action provider "${providerId}" is already registered. Unregister it first; nothing was overwritten.`),this.name="DuplicateProviderError",this.providerId=providerId}},VERBS=new Set(UNIVERSAL_VERBS);function capture(ports,error,detail){try{ports.diagnostics.capture(error,{area:"actions",detail})}catch{}}function computeEligibility(action,target,options){let restrict=options.restrict;if(!isMenuAction(action))return{status:"absent"};if(target.excludedActionIds.has(action.id))return{status:"absent"};if(restrict?.exclude?.includes(action.id))return{status:"absent"};if(restrict?.categories&&!restrict.categories.includes(action.category))return{status:"absent"};if(action.writes&&action.writes.length>0){if(target.readOnly)return{status:"absent"};let writable=new Set(target.writable.map(w=>w.name));if(!action.writes.some(name=>writable.has(name)))return{status:"absent"}}if(action.requiresAuth&&!target.auth.authenticated&&!options.authResumable)return{status:"absent"};let own=action.eligible(target);return own.status==="unavailable"?own.sentence.trim()?own:{status:"absent"}:own.status!=="unavailable-verb"?own:action.category!=="clipboard"||!VERBS.has(own.verb)?{status:"contract-break",reason:`Action "${action.id}" answered unavailable-verb but only the six universal verbs (category "clipboard") may grey; it is absent instead.`}:own.sentence.trim()?own:{status:"contract-break",reason:`Universal verb "${action.id}" greyed without a sentence; a greyed verb must say why.`}}function isMenuAction(action){return!action.surfaces||action.surfaces.includes("menu")}function createActionRegistry(options){let ports=options.ports,entries=new Map,listeners=new Set,notify=()=>{for(let l of[...listeners])l()};return{register(provider){if(entries.has(provider.id))throw new DuplicateProviderError(provider.id);let declared=provider.declaredIds?.()??[],own=new Set;for(let id of declared){if(own.has(id))throw new DuplicateActionError(id,provider.id,provider.id);own.add(id);for(let[otherId,other]of entries)if(other.declared.includes(id))throw new DuplicateActionError(id,otherId,provider.id)}let entry={provider,declared};return entries.set(provider.id,entry),notify(),()=>{entries.get(provider.id)===entry&&(entries.delete(provider.id),notify())}},async resolve(target,restrict){let authResumable=!!ports.auth,seen=new Map,out=[];for(let[providerId,{provider}]of[...entries]){let actions;try{actions=await provider.actions(target)}catch(error){capture(ports,error,{providerId,stage:"actions"});continue}for(let raw of actions){let first=seen.get(raw.id);if(first!==void 0){capture(ports,new DuplicateActionError(raw.id,first,providerId),{actionId:raw.id});continue}seen.set(raw.id,providerId);let action=raw.provider===providerId?raw:{...raw,provider:providerId},eligibility;try{eligibility=computeEligibility(action,target,{restrict:restrict??{},authResumable})}catch(error){capture(ports,error,{actionId:action.id,stage:"eligible"});continue}if(eligibility.status==="contract-break"){capture(ports,new Error(eligibility.reason),{actionId:action.id,stage:"eligible"});continue}eligibility.status!=="absent"&&out.push({action,eligibility})}}return out},providers(){return[...entries.keys()]},async get(id,target){let at=target??createClickTarget(),all=[...entries],declaring=all.filter(([,e])=>e.declared.includes(id)),order=declaring.length>0?declaring:all;for(let[providerId,{provider}]of order){let actions;try{actions=await provider.actions(at)}catch(error){capture(ports,error,{providerId,stage:"actions",actionId:id});continue}let found=actions.find(a=>a.id===id);if(found)return found.provider===providerId?found:{...found,provider:providerId}}return null},subscribe(listener){return listeners.add(listener),()=>{listeners.delete(listener)}}}}function staticActionProvider(id,actions,tier="T0"){let list=actions.map(a=>a.provider===id?a:{...a,provider:id});return{id,tier,declaredIds:()=>list.map(a=>a.id),actions:()=>list}}var alwaysEligible=()=>({status:"available"});function toJson(value){if(!(value===void 0||typeof value=="function"||typeof value=="symbol")){if(value===null||typeof value=="string"||typeof value=="boolean")return value;if(typeof value=="number")return Number.isFinite(value)?value:null;if(typeof value=="bigint")return value.toString();if(value instanceof Date)return value.toISOString();if(Array.isArray(value))return value.map(v=>toJson(v)??null);if(typeof value=="object"){let out={};for(let[k,v]of Object.entries(value)){let j=toJson(v);j!==void 0&&(out[k]=j)}return out}}}function projectValues(raw,declared,pathPrefix=""){let byName=new Map(declared.map(d=>[d.name,d])),values={},omissions=[];for(let[name,value]of Object.entries(raw)){let path=pathPrefix?`${pathPrefix}.${name}`:name,decl=byName.get(name);if(!decl){omissions.push({path,reason:"filtered"});continue}let sensitivity=resolveSensitivity(decl);if(sensitivity.classification!=="ordinary"){omissions.push({path,reason:"excluded",classification:sensitivity.classification});continue}if(!sensitivity.exportable){omissions.push({path,reason:"excluded"});continue}let json=toJson(value);json!==void 0&&(values[name]=json)}return{values,omissions}}function createProjectedReads(source){return{async values(signal){if(!source.surface||!source.declaration)return{values:{},omissions:[]};let raw=await source.surface.readValues(signal),screenValues=source.declaration.values;return projectValues(raw,screenValues)},async item(signal){let item=source.item;if(!item||!source.declaration)return null;let type=source.declaration.itemTypes?.find(t=>t.name===item.itemType);if(!type)return{values:{},omissions:[{path:item.itemType,reason:"filtered"}]};let raw=await item.readValues(signal);return projectValues(raw,type.values,item.itemType)},async live(signal){return source.surface?.readLive?source.surface.readLive(signal):{}}}}async function runAction(action,target,options){let{ports}=options;if(action.requiresAuth&&!target.auth.authenticated)return ports.auth?(ports.auth.signInThenResume({actionId:action.id,contentFingerprint:options.contentFingerprint??action.id}),{status:"auth-pending"}):(ports.diagnostics.capture(new Error(`requiresAuth action "${action.id}" ran signed out with no auth port`),{area:"actions",detail:{actionId:action.id}}),{status:"failed",error:new Error("sign-in unavailable")});let reads=createProjectedReads(options.source??{surface:null,declaration:target.declaration,item:null}),signal=options.signal??new AbortController().signal;try{return{status:"ran",outcome:await action.run(target,{reads,ports,signal})}}catch(error){ports.diagnostics.capture(error,{area:"actions",detail:{actionId:action.id,stage:"run"}});let label=typeof action.label=="string"?action.label:action.id;return ports.notify?.error(`${label} did not finish.`,"Try again; if it keeps failing, report it from the feedback button."),{status:"failed",error}}}function refused(code,message,retryable){return{ok:!1,error:{code,message,retryable}}}function isEnvelope(value){if(!value||typeof value!="object")return!1;let v=value;return v.ok===!0?!0:v.ok===!1&&!!v.error&&typeof v.error.message=="string"}function capture2(ports,error,detail){try{ports.diagnostics.capture(error,{area:"actions",detail})}catch{}}async function invokeAction(registry,id,input,options){let{ports}=options,action;try{action=await registry.get(id)}catch(error){return capture2(ports,error,{actionId:id,stage:"get"}),refused("lookup_failed",`Couldn't look up "${id}".`,!0)}if(!action)return refused("not_registered",`No action registered for "${id}".`,!1);if(!action.invoke)return refused("not_invocable",`"${id}" runs only from a menu, not by id.`,!1);let context={ports,context:options.context,signal:options.signal??new AbortController().signal},label=typeof action.label=="string"?action.label:id,failed=(error,message,retryable)=>{capture2(ports,error,{actionId:id,stage:"invoke"});try{ports.notify?.error(`${label} did not finish.`,"Try again; if it keeps failing, report it from the feedback button.")}catch{}return refused("action_failed",message,retryable)};try{let result=await action.invoke(input,context);if(!isEnvelope(result)){let error=new Error(`"${id}" answered without a result envelope ({ ok, data } | { ok: false, error }).`);return failed(error,error.message,!1)}return result}catch(error){return failed(error,error instanceof Error&&error.message?error.message:`${label} did not finish.`,!0)}}var NEVER_IN_MENUS=()=>({status:"absent"});function invocableAction(def){let surfaces=["invoke"];return{id:def.id,label:def.label,...def.description!==void 0?{description:def.description}:{},category:def.category??"app",surfaces,eligible:NEVER_IN_MENUS,run(){throw new Error(`"${def.id}" runs only by id (invokeAction), never from a menu.`)},invoke:def.invoke}}var DEFAULT_MAX_INHERITANCE_DEPTH=3;var APPLET_CATEGORY="applet",DEFAULT_TRIGGERED_BY=["person","agent","applet"],ACTION_CALLERS=["person","agent","applet","automation"],ACTION_RUNS=["page","server","mandate","navigate"],ACTION_POLICIES=["ask","auto","manual"];function compact(value){return Object.fromEntries(Object.entries(value).filter(([,v])=>v!==void 0))}var POLICY_OF_APPLY={manual:"manual",ask:"ask",auto:"auto",queued:"ask"};function writeTargetToAction(target){let applyPolicy=target.applyPolicy??"manual";return compact({name:target.name,label:target.label,description:target.description,input:target.valueKind??{jsonSchema:target.valueType==="document"?{}:{type:target.valueType}},runs:"page",triggeredBy:[...DEFAULT_TRIGGERED_BY],policy:POLICY_OF_APPLY[applyPolicy],updatesValue:target.updatesValue,mode:target.mode,patchable:target.patchable,approvalComparison:target.approvalComparison,streamOps:target.streamOps?[...target.streamOps]:void 0,destination:target.destination,groupKey:target.group,itemType:target.itemType,applyPolicy:target.applyPolicy,valueType:target.valueType,valueKind:target.valueKind,sortOrder:target.sortOrder,origin:{source:"write-target",declaredBy:"code"}})}function clientToolToAction(row){return compact({name:row.name,label:row.label,description:row.description,input:{jsonSchema:row.input_schema??{}},runs:"page",triggeredBy:["agent"],policy:row.mode==="draft"?"ask":"auto",mode:row.mode,origin:compact({source:"client-tool",surfaceName:row.surface_name,id:row.id,declaredBy:row.declared_by})})}function surfaceActionRowToAction(row){return compact({name:row.name,category:row.category,label:row.label,description:row.description,input:row.input??void 0,output:row.output??void 0,runs:row.runs,target:row.target??void 0,triggeredBy:[...row.triggered_by],policy:row.policy,updatesValue:row.updates_value??void 0,itemType:row.item_type||void 0,sortOrder:row.sort_order,origin:compact({source:"surface-action",surfaceName:row.surface_name,surfaceId:row.surface_id,id:row.id,declaredBy:row.declared_by,codeRef:row.code_ref??void 0,organizationId:row.organization_id??void 0})})}function toActionInfo(declaration,declaredOn){return compact({name:declaration.name,category:declaration.category??APPLET_CATEGORY,label:declaration.label,description:declaration.description,runs:declaration.runs,policy:declaration.policy,triggeredBy:[...declaration.triggeredBy],input:declaration.input,output:declaration.output,declaredOn,target:declaration.target,updatesValue:declaration.updatesValue,itemType:declaration.itemType,source:declaration.origin?.source})}function resolveActionChain(chain,options={}){let maxDepth=options.maxDepth??DEFAULT_MAX_INHERITANCE_DEPTH,names=chain.map(link=>link.surfaceName),seen=new Set;for(let name of names){if(seen.has(name))throw new Error(`[actions] inheritance CYCLE detected at "${name}". Fix the surface chain: ${names.join(" \u2192 ")}`);seen.add(name)}if(chain.length-1>maxDepth)throw new Error(`[actions] inheritance chain for "${names[names.length-1]}" exceeds depth ${maxDepth}: ${names.join(" \u2192 ")}`);let byName=new Map;for(let link of chain){let own=new Set;for(let action of link.actions){if(own.has(action.name))throw new Error(`[actions] surface "${link.surfaceName}" declares Action "${action.name}" twice. Names are unique; nothing was overwritten.`);own.add(action.name),byName.set(action.name,toActionInfo(action,link.surfaceName))}}return[...byName.values()]}function fail(code,message,retryable=!1,diagnostic){return{ok:!1,error:diagnostic?{code,message,retryable,diagnostic}:{code,message,retryable}}}function messageOf(error){return error instanceof Error&&error.message.trim()?error.message:typeof error=="string"&&error.trim()?error:"The run failed without saying why."}function newRunId(){let c=globalThis.crypto;return c?.randomUUID?c.randomUUID():`run-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function fillActionTarget(template,input){let source=input&&typeof input=="object"&&!Array.isArray(input)?input:{},missing=[];return{value:template.replace(/\{([A-Za-z_][A-Za-z0-9_]*)\}/g,(_,key)=>{let v=source[key];return v==null||v===""||typeof v=="object"?(missing.push(key),""):encodeURIComponent(String(v))}),missing}}function fillName(template,input){let filled=fillActionTarget(template,input);return{value:decodeURIComponent(filled.value),missing:filled.missing}}function toJson2(value){return value===void 0?null:JSON.parse(JSON.stringify(value))}function refuseCaller(info,by){return info.triggeredBy.includes(by)?info.policy==="manual"&&by!=="person"?{code:"manual_only",message:`"${info.label}" (${info.name}) runs only when a person starts it.`,retryable:!1}:null:{code:"caller_not_allowed",message:`"${info.label}" (${info.name}) can't be started by ${CALLER_WORDS[by]}; it allows ${info.triggeredBy.join(", ")||"no one"}.`,retryable:!1}}var CALLER_WORDS={person:"a person",agent:"an agent",applet:"an applet",automation:"an automation"};function absent(info,capability){return fail("capability_absent",`"${info.label}" can't run here: ${capability} isn't available on this page.`)}async function runSurfaceAction(info,input,by,ports,options={}){let refusal=refuseCaller(info,by);if(refusal)return{ok:!1,error:refusal};let context={runId:options.runId??newRunId(),by,viewerId:options.viewerId??null,surfaceName:info.declaredOn,policy:info.policy},capture3=(error,stage)=>{try{ports.diagnostics.capture(error,{area:"actions",detail:{action:info.name,runs:info.runs,stage,runId:context.runId}})}catch{}};try{if(info.source==="write-target"&&ports.door){let receipt=await ports.door.write({surfaceName:info.declaredOn,target:info.name,...info.itemType?{itemType:info.itemType}:{},...options.itemIdentity?{itemIdentity:options.itemIdentity}:{},...options.ops?{ops:options.ops}:{value:input},by,runId:context.runId},options.signal);return receipt.status==="refused"?{ok:!1,error:{code:receipt.reason,message:receipt.sentence,retryable:receipt.reason==="failed",remedy:receipt.remedy}}:{ok:!0,data:receipt}}if(info.policy==="ask"&&by!=="person"&&info.runs!=="server"){if(!ports.approvals)return fail("needs_approval",`"${info.label}" needs a person's approval, and there is no one to ask here.`);if(!await ports.approvals.ask({action:info.name,label:info.label,description:info.description,input:toJson2(input),by,surfaceName:info.declaredOn}))return fail("declined",`"${info.label}" was not approved, so it did not run.`)}switch(info.runs){case"server":{if(!ports.serverActions)return absent(info,"server actions");let filled=fillName(info.target??info.name,input);if(filled.missing.length)return fail("input_missing",`"${info.label}" needs ${filled.missing.join(", ")}.`);let response=await ports.serverActions.run({name:filled.value,input:toJson2(input),by,surface_name:info.declaredOn,policy:info.policy});return response.status==="refused"?fail("refused",response.message):{ok:!0,data:response}}case"mandate":{if(!ports.mandates)return absent(info,"running a job");if(!info.target)return fail("target_missing",`"${info.label}" names no job to run.`);let filled=fillName(info.target,input);if(filled.missing.length)return fail("input_missing",`"${info.label}" needs ${filled.missing.join(", ")}.`);let record=input&&typeof input=="object"&&!Array.isArray(input)?input:{},variables=/\{[A-Za-z_]/.test(info.target)?record.variables&&typeof record.variables=="object"?toJson2(record.variables):{}:toJson2(record),userInput=typeof record.userInput=="string"?record.userInput:void 0;return{ok:!0,data:await ports.mandates.run({alias:filled.value,variables,...userInput!==void 0?{userInput}:{},by,policy:info.policy})}}case"navigate":{if(!ports.overlay)return absent(info,"navigation");let filled=fillActionTarget(info.target??"",input);if(filled.missing.length)return fail("input_missing",`"${info.label}" needs ${filled.missing.join(", ")}.`);let to=info.target&&/^\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(info.target)?decodeURIComponent(filled.value):filled.value;return to?(ports.overlay.navigate(to),{ok:!0,data:{to}}):fail("target_missing",`"${info.label}" names no page to open.`)}case"page":return ports.pageActions?await ports.pageActions.dispatch(info.name,input,context):absent(info,"this page's actions");default:{let runs=info.runs;return fail("runs_unknown",`"${info.label}" runs as "${String(runs)}", which nothing here knows how to run.`)}}}catch(error){return capture3(error,"run"),fail("run_failed",messageOf(error),!0)}}export{ACTION_CALLERS,ACTION_CATEGORIES,ACTION_POLICIES,ACTION_RUNS,APPLET_CATEGORY,DEFAULT_TRIGGERED_BY,DuplicateActionError,DuplicateProviderError,UNIVERSAL_VERBS,alwaysEligible,clientToolToAction,computeEligibility,createActionRegistry,createClickTarget,createProjectedReads,fillActionTarget,invocableAction,invokeAction,isMenuAction,projectValues,refuseCaller,resolveActionChain,runAction,runSurfaceAction,staticActionProvider,surfaceActionRowToAction,toActionInfo,writeTargetToAction};
2
2
  //# sourceMappingURL=actions.js.map