@yaklabs-ai/plugin-sdk 0.13.1 → 0.13.3

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.
@@ -244,7 +244,7 @@ export declare function asArray(value: unknown): readonly unknown[];
244
244
  * - {@link asRecord}, {@link asArray}, {@link str}, {@link num}, {@link numLike}.
245
245
  * does_not_own:
246
246
  * - Schema-shaped validation. **Idiom-routing rule (read before reaching for these):** `z`
247
- * (re-exported from this same `@kay/plugin-sdk/kay-agent` module) is the default for
247
+ * (re-exported from this same `@bonsai/plugin-sdk/kay-agent` module) is the default for
248
248
  * anything shape-contractual — a tool's own `parameters` (via `toolParameters`), and any
249
249
  * upstream response you're going to treat as a stable contract going forward. Reach for these
250
250
  * readers only for **tolerant salvage**: pulling one or two fields out of a response whose
@@ -315,6 +315,10 @@ declare interface BackgroundTaskCompletion {
315
315
  readonly resultDelivery?: BackgroundTaskResultDelivery;
316
316
  readonly output?: string;
317
317
  readonly error?: string;
318
+ /** The thrown Error's stack, when a failed task threw one. */
319
+ readonly errorStack?: string;
320
+ /** Why a failed AGENT task's run failed, classified from what it threw; absent for other kinds. */
321
+ readonly failureReason?: RunFailureReason;
318
322
  }
319
323
 
320
324
  declare type BackgroundTaskInspector = () => Promise<string> | string;
@@ -611,6 +615,9 @@ export declare interface CreateJsonApiClientOptions {
611
615
  readonly fetch?: typeof fetch;
612
616
  }
613
617
 
618
+ /** One plugin's runner: its module, its label, and the app-specific failures it names. */
619
+ export declare function createOsascriptRunner(options: OsascriptRunnerOptions): OsascriptRunner;
620
+
614
621
  /** What the module holds at mutation time: a provider revision, the current content, or both. */
615
622
  export declare interface CurrentResourceState {
616
623
  readonly revision?: string;
@@ -831,6 +838,12 @@ declare interface ExtensionPaths {
831
838
  readonly dataDir: string;
832
839
  }
833
840
 
841
+ /**
842
+ * Several lines of text inside a code fence none of its lines can close, so a message body or an
843
+ * invitation's notes cannot pass for a heading or a field of the read around them.
844
+ */
845
+ export declare function fenced(text: string): readonly string[];
846
+
834
847
  export declare function formatIsoDate(value?: string | number | Date): string;
835
848
 
836
849
  export declare function formatNumber(n: number): string;
@@ -881,7 +894,7 @@ declare type InferToolInput<TParams extends ToolParametersWire> = TParams extend
881
894
 
882
895
  /**
883
896
  * The value a Browser Interaction driver sets as `credentialGuard` to declare that every act runs
884
- * the page-side credential guard from `@kay/interaction-page-scripts` (never type into or click a
897
+ * the page-side credential guard from `@bonsai/interaction-page-scripts` (never type into or click a
885
898
  * sign-in form). The engine refuses to register a browser driver without it.
886
899
  */
887
900
  export declare const INTERACTION_CREDENTIAL_GUARD = "kay.credential-guard/v1";
@@ -1221,7 +1234,7 @@ export declare interface JevScoreQuestion {
1221
1234
  * - The wire. The host serves `classify` over whichever route the user's Jev provider order
1222
1235
  * picks; a plugin never sees a vendor client, a vendor type, or a route.
1223
1236
  * - Credential resolution, the `jev.use` decision, the Jev-branch budget, or usage accounting.
1224
- * Those are host-side (`@kay/agent-runtime`'s `kay/jev/`).
1237
+ * Those are host-side (`@bonsai/agent-runtime`'s `kay/jev/`).
1225
1238
  * ---
1226
1239
  *
1227
1240
  * The vocabulary is Bonsai's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
@@ -1875,7 +1888,7 @@ declare interface KayAppTimeSnapshot {
1875
1888
  * The time zone the user is in, as an IANA id in the spelling ICU resolves (`America/New_York`).
1876
1889
  * One zone can have two ids, and ICU picks one: `Asia/Kolkata` comes back as `Asia/Calcutta`. So
1877
1890
  * never compare zone ids with `===`. A first-party plugin compares with `sameZone` from
1878
- * `@kay/time`. A plugin that imports only this SDK and node builtins resolves each id with
1891
+ * `@bonsai/time`. A plugin that imports only this SDK and node builtins resolves each id with
1879
1892
  * `new Intl.DateTimeFormat("en-US", { timeZone: id }).resolvedOptions().timeZone` and compares the
1880
1893
  * results. Pass `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a
1881
1894
  * time for the user.
@@ -2811,6 +2824,7 @@ declare const KayPluginManifestV1: z.ZodObject<{
2811
2824
  minKayVersion: z.ZodOptional<z.ZodString>;
2812
2825
  sdk: z.ZodOptional<z.ZodString>;
2813
2826
  }, z.core.$strict>>>;
2827
+ ownedByBonsai: z.ZodOptional<z.ZodBoolean>;
2814
2828
  dependencies: z.ZodOptional<z.ZodObject<{
2815
2829
  plugins: z.ZodOptional<z.ZodArray<z.ZodString>>;
2816
2830
  }, z.core.$strict>>;
@@ -2822,6 +2836,35 @@ declare type KnownApi = "openai-completions" | "mistral-conversations" | "openai
2822
2836
 
2823
2837
  declare type KnownProvider = "amazon-bedrock" | "ant-ling" | "anthropic" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "radius" | "typesafe" | "nvidia" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "zai-coding-cn" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "together" | "baseten" | "opencode" | "opencode-go" | "kimi-coding" | "meta" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "qwen-token-plan" | "qwen-token-plan-cn" | "qwen-token-plan-individual" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
2824
2838
 
2839
+ /**
2840
+ * A one-line label the host prints verbatim, such as an approval card's target. Line breaks,
2841
+ * other control characters, and line or paragraph separators become spaces, and invisible format
2842
+ * characters go: a zero-width joiner inside an emoji, a soft hyphen, a direction mark, a
2843
+ * zero-width space. The host refuses a target holding any of them, and drops the whole approval
2844
+ * card with it (`admitDescription` in herd-agent's `action-summary.ts`).
2845
+ */
2846
+ export declare function labelOf(value: string | null | undefined): string;
2847
+
2848
+ /**
2849
+ * ---
2850
+ * responsibility: The flat authoring-helper layer's untrusted-text surface (decision 002,
2851
+ * kay#11957): render text someone else wrote (a shared calendar's name, a contact card synced
2852
+ * from another account, an email body) into a plugin's Markdown output or an approval card
2853
+ * without it forging structure around it. Apple Mail, Calendar, and Contacts had each grown a
2854
+ * copy.
2855
+ * owns:
2856
+ * - {@link lineOf}, {@link labelOf}, {@link markdownText}, {@link fenced}.
2857
+ * does_not_own:
2858
+ * - Deciding which fields are untrusted. Every value the user does not control is; the plugin
2859
+ * routes each one through these before it reaches output.
2860
+ * ---
2861
+ */
2862
+ /**
2863
+ * A one-line field: every whitespace run, newlines included, becomes one space, so a value can
2864
+ * never open a line of its own (one that passes for an `Account:` line, for instance).
2865
+ */
2866
+ export declare function lineOf(value: string | null | undefined): string;
2867
+
2825
2868
  declare interface LineRange {
2826
2869
  readonly start: number;
2827
2870
  readonly end: number;
@@ -2839,6 +2882,17 @@ export declare function lintUriTemplate(template: UriTemplate): readonly UriTemp
2839
2882
 
2840
2883
  export declare function markdownResource(uri: string, md: string, notes?: string[]): RawResource;
2841
2884
 
2885
+ /**
2886
+ * Text placed mid-line, after a label, that cannot forge a link, an image, an HTML tag, or a
2887
+ * field: a backslash goes before `[`, `]`, `!`, and `<`; before `|`, which a plugin may use to
2888
+ * separate the fields of a one-line summary; and before a backslash, so no escape can be undone.
2889
+ *
2890
+ * It does not neutralize everything Markdown does. Line-start syntax (`#`, `>`, `-`, `1.`),
2891
+ * emphasis, code spans, and bare-URL autolinks still render, so keep the value off the start of a
2892
+ * line (behind a label, after {@link lineOf}) or use {@link fenced} for whole blocks.
2893
+ */
2894
+ export declare function markdownText(text: string): string;
2895
+
2842
2896
  /**
2843
2897
  * The execute-time surface a tool sees. These are the only fields a {@link ToolDefinition.execute}
2844
2898
  * body can read. Runtime-optionals are absent without a live session: a tool invoked from a
@@ -3275,11 +3329,183 @@ declare interface OpenRouterRouting {
3275
3329
  };
3276
3330
  }
3277
3331
 
3332
+ /**
3333
+ * The JXA half of the envelope: paste it into a script's source, then end `run(argv)` with
3334
+ * `return jsonOk(data)` or `return jsonFail(code, message)`. {@link readOsascriptOutput} reads
3335
+ * exactly what these print. Both are total: `jsonOk()` with no value answers `null` (JSON drops an
3336
+ * `undefined` key, which the reader would refuse), and `jsonFail` turns its code and message into
3337
+ * strings, so a thrown non-Error or an Error object passed as the message still reaches the
3338
+ * caller as this script's refusal, under its own code.
3339
+ */
3340
+ export declare const OSASCRIPT_ENVELOPE_JXA = "\nfunction jsonOk(data) {\n return JSON.stringify({ ok: true, data: data === undefined ? null : data });\n}\nfunction jsonFail(code, message) {\n return JSON.stringify({ ok: false, error: { code: String(code), message: String(message) } });\n}\n";
3341
+
3342
+ /** The runner's kill deadline when a call names none. */
3343
+ export declare const OSASCRIPT_TIMEOUT_MS = 30000;
3344
+
3345
+ /**
3346
+ * The argv for one script run: JavaScript, the script as a fixed `-e` constant, then `--` and the
3347
+ * dynamic values. `--` ends osascript's own option parsing: without it, a value in the first argv
3348
+ * slot that starts with `-` (a search for "-budget", a folder named "-Archive") is taken as an
3349
+ * option and the script never runs (the Apple Notes plugin verified this live). User values only
3350
+ * ever travel here, never in the script source: that is the injection boundary.
3351
+ */
3352
+ export declare function osascriptArgs(script: string, argv: readonly string[]): readonly string[];
3353
+
3354
+ /** One script run: what the error names, and the bounds the runner enforces. */
3355
+ export declare interface OsascriptCall {
3356
+ readonly operation: UriOperation;
3357
+ readonly uri: string;
3358
+ readonly signal?: AbortSignal | undefined;
3359
+ readonly maxOutputChars: number;
3360
+ /** The runner's kill deadline; absent means {@link OSASCRIPT_TIMEOUT_MS}. */
3361
+ readonly timeoutMs?: number;
3362
+ /** What to do when the output is too large; absent means "narrow the request". */
3363
+ readonly truncatedAdvice?: string;
3364
+ /**
3365
+ * Set for a script that changes the app: the sentence that ends the error when its run fails
3366
+ * before Bonsai reads its answer, such as "The event may have been created: search
3367
+ * apple-calendar://events before trying again." The script may have saved before the runner
3368
+ * failed, osascript stopped (a timeout or a cancel), or its output became unreadable. A refusal
3369
+ * the script returns itself (`jsonFail`) does not end with this sentence: a script refuses
3370
+ * before it changes anything.
3371
+ */
3372
+ readonly outcomeUnknown?: string;
3373
+ }
3374
+
3375
+ /** The runner a module's verbs use, with a simulator in the host's place when one is set. */
3376
+ export declare interface OsascriptDispatch {
3377
+ /**
3378
+ * {@link OsascriptRunner.requireExternalCli}, then the simulator's runner in the host's place.
3379
+ * The host's runner is required either way: its absence is how a not-connected service fails.
3380
+ */
3381
+ readonly requireExternalCli: (ctx: UriResolveContext, operation: UriOperation, uri: string) => UriExternalCliRunner;
3382
+ /**
3383
+ * The runner for a path that tolerates its absence (an approval card's lookup): `undefined`
3384
+ * when the host injected none, the simulator's when one is set, the host's otherwise.
3385
+ */
3386
+ readonly externalCliOf: (ctx: UriResolveContext) => UriExternalCliRunner | undefined;
3387
+ }
3388
+
3389
+ /** A failure the plugin names: its own code, and the advice that ends the message. */
3390
+ export declare interface OsascriptFailureAdvice {
3391
+ readonly code: string;
3392
+ readonly advice: string;
3393
+ }
3394
+
3395
+ /**
3396
+ * The activation options every osascript plugin's agent factory accepts
3397
+ * (`createAppleCalendarKayAgent(options)`), so the daemon's simulator roster sets each the same
3398
+ * way. Absent `simulator`, the plugin is exactly the shipped one.
3399
+ */
3400
+ export declare interface OsascriptKayAgentOptions {
3401
+ readonly simulator?: OsascriptSimulatorOptions;
3402
+ }
3403
+
3404
+ /** What a script's stdout says, once read. */
3405
+ export declare type OsascriptOutput =
3406
+ /** `jsonOk(data)`. `data` is unchecked: validate it against the script's own shape. */
3407
+ {
3408
+ readonly kind: "data";
3409
+ readonly data: unknown;
3410
+ }
3411
+ /** `jsonFail(code, message)`: the script refused on its own terms. */
3412
+ | {
3413
+ readonly kind: "refused";
3414
+ readonly code: string;
3415
+ readonly message: string;
3416
+ }
3417
+ /**
3418
+ * Not JSON, or JSON that is not an envelope (`null`, `{}`, `42`, `{"ok":false}`, and
3419
+ * `{"ok":true}` with no `data` key, which {@link OSASCRIPT_ENVELOPE_JXA}'s `jsonOk` never prints).
3420
+ */
3421
+ | {
3422
+ readonly kind: "invalid";
3423
+ readonly reason: string;
3424
+ };
3425
+
3426
+ export declare interface OsascriptRunner {
3427
+ /**
3428
+ * The host-injected runner, or the `auth_required` error the host classifies as not
3429
+ * connected: the in-handler twin of the host's pre-dispatch auth resolution.
3430
+ */
3431
+ readonly requireExternalCli: (ctx: UriResolveContext, operation: UriOperation, uri: string) => UriExternalCliRunner;
3432
+ /**
3433
+ * The runners a module's verbs use: the host's exactly when `simulator` is absent, or the
3434
+ * simulator's in its place, per dispatch, after the host's connection gate.
3435
+ */
3436
+ readonly dispatch: (simulator: OsascriptSimulatedRunner | undefined) => OsascriptDispatch;
3437
+ /**
3438
+ * Run `script` with `argv` and return the data it answered (unchecked: validate it). Every
3439
+ * other outcome throws a `UriProviderError`, except a runner that throws on its own: that
3440
+ * error passes through unchanged unless the call sets `outcomeUnknown`.
3441
+ */
3442
+ readonly runScript: (externalCli: UriExternalCliRunner, script: string, argv: readonly string[], call: OsascriptCall) => Promise<unknown>;
3443
+ /** A `UriProviderError` from this plugin's module, never retryable. */
3444
+ readonly providerError: (call: Pick<OsascriptCall, "operation" | "uri">, providerCode: string, message: string) => UriProviderError;
3445
+ /**
3446
+ * The error for a run that exited non-zero, for a caller that reads the runner's result
3447
+ * itself (a send path that reads progress markers from stderr). Ends with the call's
3448
+ * `outcomeUnknown` sentence when it has one.
3449
+ */
3450
+ readonly scriptFailure: (call: OsascriptCall, result: Pick<UriExternalCliRunResult, "stderr" | "stdout">) => UriProviderError;
3451
+ }
3452
+
3453
+ export declare interface OsascriptRunnerOptions {
3454
+ /** The URI module every error names. */
3455
+ readonly moduleId: string;
3456
+ /** The service a missing runner tells the agent to connect. */
3457
+ readonly serviceId: string;
3458
+ /** The product name that opens each message, such as "Apple Calendar". */
3459
+ readonly label: string;
3460
+ /**
3461
+ * What opens the message of a failed run; absent means "<label> automation failed". A plugin
3462
+ * that scripts no app (its JXA calls a framework directly) says "<label> script failed".
3463
+ */
3464
+ readonly failurePrefix?: string;
3465
+ /**
3466
+ * Advice for macOS refusing the Apple Event (`-1743`, "not authorized"): the Automation grant
3467
+ * is missing or revoked. Set, such a run fails `automation-denied` with this advice; absent,
3468
+ * it is an ordinary `script-failed`.
3469
+ */
3470
+ readonly automationDeniedAdvice?: string;
3471
+ /**
3472
+ * The plugin's code and advice for its app quitting mid-run: `-600` (application isn't
3473
+ * running) before the script's first Apple Event, `-609` (connection is invalid) after it.
3474
+ * Absent, such a run is an ordinary `script-failed`. The check a script makes itself
3475
+ * (`running()`, then `jsonFail`) is the plugin's, and comes back as that refusal.
3476
+ */
3477
+ readonly appNotRunning?: OsascriptFailureAdvice;
3478
+ }
3479
+
3480
+ /** A plugin's simulator, as the runner sees it: the runner one dispatch uses in the host's place. */
3481
+ export declare interface OsascriptSimulatedRunner {
3482
+ readonly runnerFor: (ctx: UriResolveContext) => UriExternalCliRunner;
3483
+ }
3484
+
3485
+ /**
3486
+ * How a plugin is told to serve its module from its simulator instead of osascript: the one
3487
+ * option shape every osascript plugin's agent factory accepts as `simulator`. Only the daemon's
3488
+ * URI simulator roster sets it, for evals and dev; an ordinary install never does.
3489
+ */
3490
+ export declare interface OsascriptSimulatorOptions {
3491
+ /** The directory holding the simulator's world; the daemon's process config names it. */
3492
+ readonly stateDir: string;
3493
+ }
3494
+
3278
3495
  export declare function parseLineSelector(input: string): {
3279
3496
  address: string;
3280
3497
  selector: LineSelector;
3281
3498
  };
3282
3499
 
3500
+ /**
3501
+ * The script and argv of a request {@link osascriptArgs} built, or `undefined` for any other
3502
+ * argv. A simulated runner reads requests through this, so the argv layout has one owner.
3503
+ */
3504
+ export declare function parseOsascriptArgs(args: readonly string[]): {
3505
+ readonly script: string;
3506
+ readonly argv: readonly string[];
3507
+ } | undefined;
3508
+
3283
3509
  export declare function parseUriConnectionSelector(input: string): UriConnectionSelectorParse;
3284
3510
 
3285
3511
  /** Parse either dialect into the normalized replacement list. */
@@ -3422,6 +3648,10 @@ declare const PluginCapabilityRefusalV1: z.ZodObject<{
3422
3648
  target: z.ZodLiteral<"kay.app">;
3423
3649
  slug: z.ZodLiteral<"skills.read">;
3424
3650
  envelope: z.ZodObject<{}, z.core.$strict>;
3651
+ }, z.core.$strict>, z.ZodObject<{
3652
+ target: z.ZodLiteral<"kay.app">;
3653
+ slug: z.ZodLiteral<"tools.describe">;
3654
+ envelope: z.ZodObject<{}, z.core.$strict>;
3425
3655
  }, z.core.$strict>, z.ZodObject<{
3426
3656
  target: z.ZodLiteral<"kay.app">;
3427
3657
  slug: z.ZodLiteral<"workspace.command">;
@@ -3884,6 +4114,9 @@ declare interface RawResourceMetadata {
3884
4114
  */
3885
4115
  export declare function readBodyWithByteCap(response: Response, maxBytes: number): Promise<ByteCapReadResult | undefined>;
3886
4116
 
4117
+ /** Read a script's stdout. Never throws: anything but a well-formed envelope is `invalid`. */
4118
+ export declare function readOsascriptOutput(stdout: string): OsascriptOutput;
4119
+
3887
4120
  /**
3888
4121
  * The capability⇄service auth binding. A registration carrying this is gated on `serviceId`'s
3889
4122
  * connectivity; the runtime answers "is this capability authorized?" from this plus vault state.
@@ -3998,6 +4231,28 @@ declare interface ResolveTokenSuccess {
3998
4231
  readonly auth: ResolvedAuth;
3999
4232
  }
4000
4233
 
4234
+ /**
4235
+ * Pure, provider-neutral classification of a failed model run.
4236
+ *
4237
+ * This is a leaf module with no runtime imports, because two callers that
4238
+ * cannot share a bundle must reach the same verdict: the kernel failure path
4239
+ * (`run-error.ts`, which reaches Pi and Node) and the browser-safe interactive
4240
+ * reducer that projects an errored message for a surface to render. Routing the
4241
+ * reducer through `run-error.ts` would drag `pi-agent-core` into the renderer
4242
+ * bundle; duplicating the rules there would let the reason a run was *retried
4243
+ * for* drift from the reason a user is *told about*.
4244
+ *
4245
+ * The leaf rule is why {@link readableFailureText} carries its own small HTML
4246
+ * extractor instead of reaching for `core/web/markdown.ts`. That module imports
4247
+ * `@herd/plugin-primitives`, and the browser-safety guard externalizes bare
4248
+ * specifiers, so it could not prove the import stays renderer-safe. It is also
4249
+ * the wrong tool: it emits markdown into what must remain a plain diagnostic,
4250
+ * and it discards `<head>`, where a gateway page puts the one line naming the
4251
+ * failure.
4252
+ */
4253
+ /** Provider-neutral factual category for a failed model run. */
4254
+ declare type RunFailureReason = "auth" | "content_blocked" | "context_overflow" | "invalid_request" | "model_unavailable" | "network" | "overloaded" | "quota_exhausted" | "rate_limit" | "safeguard_block" | "seat_unpaid" | "server_error" | "stream_interrupted" | "timeout" | "unknown";
4255
+
4001
4256
  export declare type SchemaInput = z.ZodType | JsonSchema;
4002
4257
 
4003
4258
  /** One all-of arm in an ordered scope requirement. */
@@ -4939,6 +5194,12 @@ declare interface UriHelp {
4939
5194
  readonly templates?: readonly UriTemplate[];
4940
5195
  readonly examples?: readonly UriExample[];
4941
5196
  readonly notes?: readonly string[];
5197
+ /**
5198
+ * Set when this help, for the address it was asked about, carries text a third party wrote and
5199
+ * the module relays as it received it (an MCP server's own tool names and descriptions), rather
5200
+ * than text the module's author wrote. Absent: the module's own text.
5201
+ */
5202
+ readonly thirdPartyContent?: true;
4942
5203
  }
4943
5204
 
4944
5205
  declare interface UriHintTriggers {
@@ -5797,7 +6058,7 @@ declare interface UriValidationMessage {
5797
6058
  * applies label changes"), never wire mechanics or URI shapes. Verbs the
5798
6059
  * module does not support are omitted; at runtime a supported verb with no
5799
6060
  * entry simply renders undocumented (fail-open metadata) — but for a plugin's
5800
- * `kay.agent` URI modules, `auditPluginDisclosure` (`@kay/plugin-sdk/
6061
+ * `kay.agent` URI modules, `auditPluginDisclosure` (`@bonsai/plugin-sdk/
5801
6062
  * disclosure`) enforces coverage of every supported verb at authoring/load
5802
6063
  * time.
5803
6064
  *
package/dist/kay-agent.js CHANGED
@@ -1011,7 +1011,7 @@ async function readBodyWithByteCap(response, maxBytes) {
1011
1011
  }
1012
1012
 
1013
1013
  // packages/plugin-sdk/dist/kay-agent/index.js
1014
- import { z as z6 } from "zod";
1014
+ import { z as z7 } from "zod";
1015
1015
 
1016
1016
  // packages/plugin-sdk/dist/kay-agent/http-client.js
1017
1017
  var PluginApiError = class extends Error {
@@ -1164,6 +1164,163 @@ function bytesToBase64(bytes) {
1164
1164
  return output;
1165
1165
  }
1166
1166
 
1167
+ // packages/plugin-sdk/dist/kay-agent/osascript.js
1168
+ import { z as z6 } from "zod";
1169
+ var OSASCRIPT_TIMEOUT_MS = 3e4;
1170
+ var OSASCRIPT_ENVELOPE_JXA = `
1171
+ function jsonOk(data) {
1172
+ return JSON.stringify({ ok: true, data: data === undefined ? null : data });
1173
+ }
1174
+ function jsonFail(code, message) {
1175
+ return JSON.stringify({ ok: false, error: { code: String(code), message: String(message) } });
1176
+ }
1177
+ `;
1178
+ var envelopeSchema = z6.discriminatedUnion("ok", [
1179
+ z6.object({ ok: z6.literal(true), data: z6.unknown() }),
1180
+ z6.object({
1181
+ ok: z6.literal(false),
1182
+ error: z6.object({ code: z6.string(), message: z6.string() })
1183
+ })
1184
+ ]);
1185
+ function readOsascriptOutput(stdout) {
1186
+ let json;
1187
+ try {
1188
+ json = JSON.parse(stdout);
1189
+ } catch (error) {
1190
+ return {
1191
+ kind: "invalid",
1192
+ reason: `output that was not valid JSON: ${error instanceof Error ? error.message : String(error)}`
1193
+ };
1194
+ }
1195
+ const envelope = envelopeSchema.safeParse(json);
1196
+ if (!envelope.success) {
1197
+ return {
1198
+ kind: "invalid",
1199
+ reason: "output in a shape Bonsai does not know."
1200
+ };
1201
+ }
1202
+ return envelope.data.ok ? { kind: "data", data: envelope.data.data } : {
1203
+ kind: "refused",
1204
+ code: envelope.data.error.code,
1205
+ message: envelope.data.error.message
1206
+ };
1207
+ }
1208
+ function osascriptArgs(script, argv) {
1209
+ return ["-l", "JavaScript", "-e", script, "--", ...argv];
1210
+ }
1211
+ function parseOsascriptArgs(args) {
1212
+ const [language, name, flag, script, separator, ...argv] = args;
1213
+ if (language !== "-l" || name !== "JavaScript" || flag !== "-e" || script === void 0 || separator !== "--") {
1214
+ return void 0;
1215
+ }
1216
+ return { script, argv };
1217
+ }
1218
+ function withOutcome(call, message) {
1219
+ if (call.outcomeUnknown === void 0)
1220
+ return message;
1221
+ const sentence = /[.!?]$/.test(message) ? message : `${message}.`;
1222
+ return `${sentence} ${call.outcomeUnknown}`;
1223
+ }
1224
+ function createOsascriptRunner(options) {
1225
+ const failurePrefix = options.failurePrefix ?? `${options.label} automation failed`;
1226
+ const providerError = (call, providerCode, message) => new UriProviderError({
1227
+ moduleId: options.moduleId,
1228
+ operation: call.operation,
1229
+ uri: call.uri,
1230
+ message,
1231
+ providerCode,
1232
+ retryable: false
1233
+ });
1234
+ const requireExternalCli = (ctx, operation, uri) => {
1235
+ const externalCli = ctx.auth?.externalCli;
1236
+ if (externalCli === void 0) {
1237
+ throw new UriProviderError({
1238
+ moduleId: options.moduleId,
1239
+ operation,
1240
+ uri,
1241
+ message: `${options.label} access is not connected. Run service_connect for ${options.serviceId}.`,
1242
+ providerCode: "auth_required"
1243
+ });
1244
+ }
1245
+ return externalCli;
1246
+ };
1247
+ const dispatch = (simulator) => simulator === void 0 ? {
1248
+ requireExternalCli,
1249
+ externalCliOf: (ctx) => ctx.auth?.externalCli
1250
+ } : {
1251
+ requireExternalCli: (ctx, operation, uri) => {
1252
+ requireExternalCli(ctx, operation, uri);
1253
+ return simulator.runnerFor(ctx);
1254
+ },
1255
+ externalCliOf: (ctx) => ctx.auth?.externalCli === void 0 ? void 0 : simulator.runnerFor(ctx)
1256
+ };
1257
+ const scriptFailure = (call, result) => {
1258
+ const detail = (result.stderr.trim() !== "" ? result.stderr : result.stdout).trim();
1259
+ const base = `${failurePrefix}: ${detail !== "" ? detail : "osascript exited with a non-zero status."}`;
1260
+ const denied = options.automationDeniedAdvice;
1261
+ if (denied !== void 0 && (/-1743/.test(detail) || /not authorized/i.test(detail))) {
1262
+ return providerError(call, "automation-denied", withOutcome(call, `${base} ${denied}`));
1263
+ }
1264
+ const notRunning = options.appNotRunning;
1265
+ if (notRunning !== void 0 && (/-60[09]\b/.test(detail) || /isn.t running/i.test(detail))) {
1266
+ return providerError(call, notRunning.code, withOutcome(call, `${base} ${notRunning.advice}`));
1267
+ }
1268
+ return providerError(call, "script-failed", withOutcome(call, base));
1269
+ };
1270
+ const runScript = async (externalCli, script, argv, call) => {
1271
+ let result;
1272
+ try {
1273
+ result = await externalCli.run({
1274
+ args: osascriptArgs(script, argv),
1275
+ timeoutMs: call.timeoutMs ?? OSASCRIPT_TIMEOUT_MS,
1276
+ maxOutputChars: call.maxOutputChars,
1277
+ ...call.signal !== void 0 ? { signal: call.signal } : {}
1278
+ });
1279
+ } catch (error) {
1280
+ if (call.outcomeUnknown === void 0)
1281
+ throw error;
1282
+ throw providerError(call, "script-failed", withOutcome(call, `${failurePrefix}: ${error instanceof Error ? error.message : String(error)}`));
1283
+ }
1284
+ if (result.exitCode !== 0)
1285
+ throw scriptFailure(call, result);
1286
+ if (result.stdoutTruncated === true) {
1287
+ throw providerError(call, "output-truncated", withOutcome(call, `${options.label} script output was truncated; ${call.truncatedAdvice ?? "narrow the request"}.`));
1288
+ }
1289
+ const output = readOsascriptOutput(result.stdout);
1290
+ switch (output.kind) {
1291
+ case "data":
1292
+ return output.data;
1293
+ case "refused":
1294
+ throw providerError(call, output.code, output.message);
1295
+ case "invalid":
1296
+ throw providerError(call, "output-invalid", withOutcome(call, `${options.label} script produced ${output.reason}`));
1297
+ }
1298
+ };
1299
+ return {
1300
+ requireExternalCli,
1301
+ dispatch,
1302
+ runScript,
1303
+ providerError,
1304
+ scriptFailure
1305
+ };
1306
+ }
1307
+
1308
+ // packages/plugin-sdk/dist/kay-agent/untrusted-text.js
1309
+ function lineOf(value) {
1310
+ return (value ?? "").trim().replace(/\s+/g, " ");
1311
+ }
1312
+ function labelOf(value) {
1313
+ return lineOf((value ?? "").replace(/[\p{Cc}\p{Zl}\p{Zp}]/gu, " ").replace(/\p{Cf}/gu, ""));
1314
+ }
1315
+ function markdownText(text) {
1316
+ return text.replace(/[\\[\]!<|]/g, (character) => `\\${character}`);
1317
+ }
1318
+ function fenced(text) {
1319
+ const runs = text.match(/`+/g) ?? [];
1320
+ const fence = "`".repeat(Math.max(3, ...runs.map((run) => run.length + 1)));
1321
+ return [`${fence}text`, text, fence];
1322
+ }
1323
+
1167
1324
  // packages/plugin-sdk/dist/kay-agent/advertisement.js
1168
1325
  function defineKayAgentAdvertisement(advertisement) {
1169
1326
  return advertisement;
@@ -1399,6 +1556,8 @@ export {
1399
1556
  KayAgentCapabilityError,
1400
1557
  KayAgentWebSessionError,
1401
1558
  OBSERVATION_MIME,
1559
+ OSASCRIPT_ENVELOPE_JXA,
1560
+ OSASCRIPT_TIMEOUT_MS,
1402
1561
  PluginApiError,
1403
1562
  SearchProviderError,
1404
1563
  URI_TEXT_EDIT_SHAPE_SUMMARY,
@@ -1420,28 +1579,36 @@ export {
1420
1579
  contentResult,
1421
1580
  createFallbackOnlyWithJev,
1422
1581
  createJsonApiClient,
1582
+ createOsascriptRunner,
1423
1583
  declareProducedResources,
1424
1584
  defineAuthedTool,
1425
1585
  defineKayAgentAdvertisement,
1426
1586
  defineTool,
1427
1587
  describeUriTextEditTarget,
1588
+ fenced,
1428
1589
  formatIsoDate,
1429
1590
  formatNumber,
1430
1591
  getBytes,
1431
1592
  isDelegatedRefreshRejected,
1432
1593
  jsonResource,
1594
+ labelOf,
1595
+ lineOf,
1433
1596
  lintUriHelpContracts,
1434
1597
  lintUriTemplate,
1435
1598
  markdownResource,
1599
+ markdownText,
1436
1600
  num,
1437
1601
  numLike,
1438
1602
  observationFromResource,
1439
1603
  observationResource,
1604
+ osascriptArgs,
1440
1605
  parseLineSelector,
1606
+ parseOsascriptArgs,
1441
1607
  parseUriConnectionSelector,
1442
1608
  parseUriTextEditPayload,
1443
1609
  payload,
1444
1610
  readBodyWithByteCap,
1611
+ readOsascriptOutput,
1445
1612
  str,
1446
1613
  textResult,
1447
1614
  toJsonSchema,
@@ -1452,5 +1619,5 @@ export {
1452
1619
  uriTextEditPayloadSchema,
1453
1620
  withResolvedAuth,
1454
1621
  withResolvedSearchProvider,
1455
- z6 as z
1622
+ z7 as z
1456
1623
  };