@ericsanchezok/synergy-util 3.0.22 → 3.0.23

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/dist/activity.js CHANGED
@@ -41,7 +41,9 @@ export const ActivityDerivedMetadataSchema = z.object({
41
41
  .optional(),
42
42
  });
43
43
  const TOOL_CATEGORIES = {
44
- websearch: "web",
44
+ computer_apps: "generic",
45
+ computer_observe: "generic",
46
+ computer_action: "generic",
45
47
  webfetch: "web",
46
48
  browser_navigation: "browser",
47
49
  browser_snapshot: "browser",
@@ -63,8 +65,6 @@ const TOOL_CATEGORIES = {
63
65
  browser_assets: "browser",
64
66
  browser_annotate: "browser",
65
67
  browser_view: "browser",
66
- arxiv_search: "search",
67
- arxiv_download: "search",
68
68
  grep: "search",
69
69
  file_search: "search",
70
70
  scan_files: "search",
@@ -154,6 +154,7 @@ const TOOL_CATEGORIES = {
154
154
  worktree_enter: "config",
155
155
  worktree_leave: "config",
156
156
  worktree_list: "config",
157
+ agent_config: "config",
157
158
  connect: "network",
158
159
  inspire_status: "config",
159
160
  inspire_config: "config",
@@ -178,6 +179,7 @@ const TOOL_CATEGORIES = {
178
179
  github_deliver_fix: "communication",
179
180
  openai_image_gen: "communication",
180
181
  openai_image_edit: "communication",
182
+ speak: "communication",
181
183
  render: "analyze",
182
184
  attach: "communication",
183
185
  response_card: "communication",
@@ -224,6 +226,7 @@ const PATTERN_FALLBACKS = [
224
226
  ];
225
227
  const ACTIVITY_FAMILIES = new Set(ACTIVITY_FAMILY_ORDER);
226
228
  const EXTERNAL_ACTION_TOOLS = new Set([
229
+ "computer_action",
227
230
  "email_send",
228
231
  "email_mark_read",
229
232
  "session_send",
@@ -249,6 +252,7 @@ const PRODUCTION_COMMUNICATION_TOOLS = new Set([
249
252
  "response_card",
250
253
  "openai_image_gen",
251
254
  "openai_image_edit",
255
+ "speak",
252
256
  "generate_image",
253
257
  "edit_image",
254
258
  ]);
@@ -266,6 +270,17 @@ const COORDINATION_RECEIPT_TOOLS = new Set([
266
270
  "blueprint_loop_stop",
267
271
  ]);
268
272
  const ACTIVITY_PRESENTATION_BOUNDARY_TOOLS = new Set(["render"]);
273
+ // Built-in remote MCP search families stay visible as individual cards in
274
+ // the activity timeline instead of being folded into grouped summary rows.
275
+ // Their renderers are presentation boundaries with per-query structure the
276
+ // user should be able to inspect after the turn (the same reason `render`
277
+ // is a boundary above).
278
+ const ACTIVITY_PRESENTATION_BOUNDARY_PREFIXES = ["mcp__anysearch__", "mcp__scholight__"];
279
+ function isPresentationBoundaryTool(tool) {
280
+ if (ACTIVITY_PRESENTATION_BOUNDARY_TOOLS.has(tool))
281
+ return true;
282
+ return ACTIVITY_PRESENTATION_BOUNDARY_PREFIXES.some((prefix) => tool.startsWith(prefix));
283
+ }
269
284
  function record(value) {
270
285
  if (!value || typeof value !== "object" || Array.isArray(value))
271
286
  return {};
@@ -292,7 +307,7 @@ function firstString(...values) {
292
307
  }
293
308
  }
294
309
  export function isActivityGroupableTool(tool, metadata = {}) {
295
- if (ACTIVITY_PRESENTATION_BOUNDARY_TOOLS.has(tool))
310
+ if (isPresentationBoundaryTool(tool))
296
311
  return false;
297
312
  const policy = toolDisplayPolicy(metadata);
298
313
  return !policy.toolCardHidden && !policy.mediaGeneration;
@@ -10,7 +10,7 @@ export interface SynergyCapabilityDefinition {
10
10
  nonBypassable?: boolean;
11
11
  }
12
12
  export declare const SYNERGY_CAPABILITY_DETAILS: Record<string, SynergyCapabilityDefinition>;
13
- export declare const SYNERGY_PROFILE_CAPABILITIES: readonly ["file_read", "file_write", "shell_read", "shell", "shell_branch_mutation", "shell_remote_execute", "shell_remote_publish", "shell_remote_write", "shell_destructive", "shell_hardline", "file_external_read", "file_external_write", "network_read", "network_request", "mcp_invoke", "mcp_spawn", "session_data", "workspace_data", "config:read", "config:write", "secrets", "task", "prompt_transform", "compaction_transform", "tool_execution_hook", "permission_hook", "event_hook", "config_hook", "identity_act", "communication_email", "channel_outbound", "platform_control", "protected_op", "session_state", "browser_interact", "browser_inspect", "browser_eval_readonly", "browser_eval_trusted", "browser_clipboard", "browser_upload", "browser_coordinate", "browser_download", "browser_emulation"];
13
+ export declare const SYNERGY_PROFILE_CAPABILITIES: readonly ["file_read", "file_write", "shell_read", "shell", "shell_branch_mutation", "shell_remote_execute", "shell_remote_publish", "shell_remote_write", "shell_destructive", "shell_hardline", "file_external_read", "file_external_write", "network_read", "network_request", "mcp_invoke", "mcp_spawn", "session_data", "workspace_data", "config:read", "config:write", "secrets", "task", "prompt_transform", "compaction_transform", "tool_execution_hook", "permission_hook", "event_hook", "config_hook", "identity_act", "communication_email", "channel_outbound", "platform_control", "protected_op", "session_state", "browser_interact", "computer_observe", "computer_interact", "browser_inspect", "browser_eval_readonly", "browser_eval_trusted", "browser_clipboard", "browser_upload", "browser_coordinate", "browser_download", "browser_emulation"];
14
14
  export declare const SYNERGY_PERMISSION_CAPABILITY: Record<string, string>;
15
15
  export declare function permissionCapability(permission: string): string;
16
16
  export declare function capabilityNonBypassable(capability: string): boolean;
@@ -13,6 +13,20 @@ export const SYNERGY_CAPABILITY_CATEGORIES = [
13
13
  "platform",
14
14
  ];
15
15
  export const SYNERGY_CAPABILITY_DETAILS = {
16
+ computer_observe: {
17
+ category: "platform",
18
+ severity: "high",
19
+ title: "Observe desktop applications",
20
+ description: "Can enumerate native applications and read screenshots and accessibility information in Full Access mode.",
21
+ nonBypassable: true,
22
+ },
23
+ computer_interact: {
24
+ category: "platform",
25
+ severity: "high",
26
+ title: "Control desktop applications",
27
+ description: "Can operate observed native application windows using background input in Full Access mode.",
28
+ nonBypassable: true,
29
+ },
16
30
  shell_read: {
17
31
  category: "runtime",
18
32
  severity: "low",
@@ -334,6 +348,8 @@ export const SYNERGY_PROFILE_CAPABILITIES = [
334
348
  "protected_op",
335
349
  "session_state",
336
350
  "browser_interact",
351
+ "computer_observe",
352
+ "computer_interact",
337
353
  "browser_inspect",
338
354
  "browser_eval_readonly",
339
355
  "browser_eval_trusted",
@@ -360,9 +376,6 @@ export const SYNERGY_PERMISSION_CAPABILITY = {
360
376
  bash: "shell",
361
377
  external_directory: "file_external_read",
362
378
  webfetch: "network_read",
363
- websearch: "network_read",
364
- arxiv_search: "network_read",
365
- arxiv_download: "network_read",
366
379
  download: "network_read",
367
380
  network_request: "network_request",
368
381
  scan_document: "file_read",
@@ -396,6 +409,7 @@ export const SYNERGY_PERMISSION_CAPABILITY = {
396
409
  doom_loop: "session_state",
397
410
  worktree_enter: "file_write",
398
411
  worktree_leave: "file_write",
412
+ agent_config: "config:write",
399
413
  session_data: "session_data",
400
414
  workspace_data: "workspace_data",
401
415
  "config:read": "config:read",
@@ -30,6 +30,8 @@ export declare namespace ModelLimit {
30
30
  * footprint is their sum.
31
31
  */
32
32
  function actualInput(tokens: TokenUsage): number;
33
+ function totalTokens(tokens: TokenUsage): number;
34
+ function nonReasoningOutput(tokens: TokenUsage): number;
33
35
  /**
34
36
  * Compute how many tokens are available for input within a model's context.
35
37
  *
@@ -20,6 +20,14 @@ export var ModelLimit;
20
20
  return tokens.input + tokens.cache.read + tokens.cache.write;
21
21
  }
22
22
  ModelLimit.actualInput = actualInput;
23
+ function totalTokens(tokens) {
24
+ return actualInput(tokens) + tokens.output;
25
+ }
26
+ ModelLimit.totalTokens = totalTokens;
27
+ function nonReasoningOutput(tokens) {
28
+ return Math.max(0, tokens.output - tokens.reasoning);
29
+ }
30
+ ModelLimit.nonReasoningOutput = nonReasoningOutput;
23
31
  /**
24
32
  * Compute how many tokens are available for input within a model's context.
25
33
  *
@@ -0,0 +1,13 @@
1
+ export declare namespace PluginToolId {
2
+ function format(pluginId: string, toolId: string): string;
3
+ function parse(id: string): {
4
+ pluginId: string;
5
+ toolId: string;
6
+ } | undefined;
7
+ function is(id: string): boolean;
8
+ }
9
+ export declare namespace PluginId {
10
+ function isValid(id: string): boolean;
11
+ function normalize(id: string): string;
12
+ function mcpServerKey(pluginId: string, serverKey: string): string;
13
+ }
@@ -0,0 +1,33 @@
1
+ export var PluginToolId;
2
+ (function (PluginToolId) {
3
+ function format(pluginId, toolId) {
4
+ return `plugin__${pluginId}__${toolId}`;
5
+ }
6
+ PluginToolId.format = format;
7
+ function parse(id) {
8
+ const match = id.match(/^plugin__([^_]+(?:_[^_]+)*?)__([^_].*)$/);
9
+ if (!match)
10
+ return undefined;
11
+ return { pluginId: match[1], toolId: match[2] };
12
+ }
13
+ PluginToolId.parse = parse;
14
+ function is(id) {
15
+ return id.startsWith("plugin__");
16
+ }
17
+ PluginToolId.is = is;
18
+ })(PluginToolId || (PluginToolId = {}));
19
+ export var PluginId;
20
+ (function (PluginId) {
21
+ function isValid(id) {
22
+ return /^[a-z][a-z0-9_-]*$/i.test(id);
23
+ }
24
+ PluginId.isValid = isValid;
25
+ function normalize(id) {
26
+ return id.trim().toLowerCase();
27
+ }
28
+ PluginId.normalize = normalize;
29
+ function mcpServerKey(pluginId, serverKey) {
30
+ return `${pluginId}::${serverKey}`;
31
+ }
32
+ PluginId.mcpServerKey = mcpServerKey;
33
+ })(PluginId || (PluginId = {}));
@@ -72,8 +72,10 @@ async function queryProcessStartIdentity(pid) {
72
72
  // recycled within that second is not detected. That failure is fail-safe:
73
73
  // the stale lock waits out the acquire timeout instead of a live owner
74
74
  // being displaced.
75
- const result = await execFileAsync("ps", ["-p", String(pid), "-o", "lstart="]).catch(() => ({ stdout: "" }));
76
- const startedAt = Date.parse(result.stdout.trim());
75
+ const result = await execFileAsync("ps", ["-p", String(pid), "-o", "lstart="], {
76
+ env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
77
+ }).catch(() => ({ stdout: "" }));
78
+ const startedAt = Date.parse(result.stdout.trim() + " UTC");
77
79
  return Number.isNaN(startedAt) ? undefined : `unix:${startedAt}`;
78
80
  }
79
81
  async function linuxBootId() {
@@ -0,0 +1,89 @@
1
+ export type AuthImportResult = ({
2
+ type: "success";
3
+ provider?: string;
4
+ } & ({
5
+ refresh: string;
6
+ access: string;
7
+ expires: number;
8
+ } | {
9
+ key: string;
10
+ })) | {
11
+ type: "failed";
12
+ message?: string;
13
+ };
14
+ export type AuthOuathResult = {
15
+ url: string;
16
+ instructions: string;
17
+ } & ({
18
+ method: "auto";
19
+ callback(): Promise<({
20
+ type: "success";
21
+ provider?: string;
22
+ } & ({
23
+ refresh: string;
24
+ access: string;
25
+ expires: number;
26
+ } | {
27
+ key: string;
28
+ })) | {
29
+ type: "failed";
30
+ }>;
31
+ } | {
32
+ method: "code";
33
+ callback(code: string): Promise<({
34
+ type: "success";
35
+ provider?: string;
36
+ } & ({
37
+ refresh: string;
38
+ access: string;
39
+ expires: number;
40
+ } | {
41
+ key: string;
42
+ })) | {
43
+ type: "failed";
44
+ }>;
45
+ });
46
+ export type AuthPrompt = {
47
+ type: "text";
48
+ key: string;
49
+ message: string;
50
+ placeholder?: string;
51
+ validate?: (value: string) => string | undefined;
52
+ condition?: (inputs: Record<string, string>) => boolean;
53
+ } | {
54
+ type: "select";
55
+ key: string;
56
+ message: string;
57
+ options: Array<{
58
+ label: string;
59
+ value: string;
60
+ hint?: string;
61
+ }>;
62
+ condition?: (inputs: Record<string, string>) => boolean;
63
+ };
64
+ export type AuthHook<Auth, Provider> = {
65
+ provider: string;
66
+ loader?: (auth: () => Promise<Auth>, provider: Provider) => Promise<Record<string, unknown>>;
67
+ methods: Array<{
68
+ type: "oauth";
69
+ label: string;
70
+ prompts?: AuthPrompt[];
71
+ authorize(inputs?: Record<string, string>): Promise<AuthOuathResult>;
72
+ } | {
73
+ type: "api";
74
+ label: string;
75
+ prompts?: AuthPrompt[];
76
+ authorize?(inputs?: Record<string, string>): Promise<{
77
+ type: "success";
78
+ key: string;
79
+ provider?: string;
80
+ } | {
81
+ type: "failed";
82
+ }>;
83
+ } | {
84
+ type: "import";
85
+ label: string;
86
+ prompts?: AuthPrompt[];
87
+ import(inputs?: Record<string, string>): Promise<AuthImportResult>;
88
+ }>;
89
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export interface KeyEncodingResult {
2
+ data: string;
3
+ warnings: string[];
4
+ }
5
+ export declare function encodeKeySequence(keys: string[]): KeyEncodingResult;
@@ -0,0 +1,127 @@
1
+ const ESC = "\x1b";
2
+ const CR = "\r";
3
+ const TAB = "\t";
4
+ const BACKSPACE = "\x7f";
5
+ const namedKeyMap = new Map([
6
+ ["enter", CR],
7
+ ["return", CR],
8
+ ["tab", TAB],
9
+ ["escape", ESC],
10
+ ["esc", ESC],
11
+ ["space", " "],
12
+ ["bspace", BACKSPACE],
13
+ ["backspace", BACKSPACE],
14
+ ["up", `${ESC}[A`],
15
+ ["down", `${ESC}[B`],
16
+ ["right", `${ESC}[C`],
17
+ ["left", `${ESC}[D`],
18
+ ["home", `${ESC}[1~`],
19
+ ["end", `${ESC}[4~`],
20
+ ["pageup", `${ESC}[5~`],
21
+ ["pagedown", `${ESC}[6~`],
22
+ ["insert", `${ESC}[2~`],
23
+ ["delete", `${ESC}[3~`],
24
+ ["f1", `${ESC}OP`],
25
+ ["f2", `${ESC}OQ`],
26
+ ["f3", `${ESC}OR`],
27
+ ["f4", `${ESC}OS`],
28
+ ["f5", `${ESC}[15~`],
29
+ ["f6", `${ESC}[17~`],
30
+ ["f7", `${ESC}[18~`],
31
+ ["f8", `${ESC}[19~`],
32
+ ["f9", `${ESC}[20~`],
33
+ ["f10", `${ESC}[21~`],
34
+ ["f11", `${ESC}[23~`],
35
+ ["f12", `${ESC}[24~`],
36
+ ]);
37
+ export function encodeKeySequence(keys) {
38
+ const warnings = [];
39
+ let data = "";
40
+ for (const token of keys) {
41
+ data += encodeKeyToken(token, warnings);
42
+ }
43
+ return { data, warnings };
44
+ }
45
+ function encodeKeyToken(raw, warnings) {
46
+ const token = raw.trim();
47
+ if (!token)
48
+ return "";
49
+ // Handle ^X notation for Ctrl
50
+ if (token.length === 2 && token.startsWith("^")) {
51
+ const ctrl = toCtrlChar(token[1]);
52
+ if (ctrl)
53
+ return ctrl;
54
+ }
55
+ const parsed = parseModifiers(token);
56
+ const base = parsed.base;
57
+ const baseLower = base.toLowerCase();
58
+ // Handle Shift+Tab
59
+ if (baseLower === "tab" && parsed.mods.shift) {
60
+ return `${ESC}[Z`;
61
+ }
62
+ // Check named keys
63
+ const baseSeq = namedKeyMap.get(baseLower);
64
+ if (baseSeq) {
65
+ if (parsed.mods.alt) {
66
+ return `${ESC}${baseSeq}`;
67
+ }
68
+ return baseSeq;
69
+ }
70
+ // Single character with modifiers
71
+ if (base.length === 1) {
72
+ return applyCharModifiers(base, parsed.mods);
73
+ }
74
+ if (parsed.hasModifiers) {
75
+ warnings.push(`Unknown key "${base}" for modifiers; sending literal.`);
76
+ }
77
+ return base;
78
+ }
79
+ function parseModifiers(token) {
80
+ const mods = { ctrl: false, alt: false, shift: false };
81
+ let rest = token;
82
+ let sawModifiers = false;
83
+ while (rest.length > 2 && rest[1] === "-") {
84
+ const mod = rest[0].toLowerCase();
85
+ if (mod === "c") {
86
+ mods.ctrl = true;
87
+ }
88
+ else if (mod === "m") {
89
+ mods.alt = true;
90
+ }
91
+ else if (mod === "s") {
92
+ mods.shift = true;
93
+ }
94
+ else {
95
+ break;
96
+ }
97
+ sawModifiers = true;
98
+ rest = rest.slice(2);
99
+ }
100
+ return { mods, base: rest, hasModifiers: sawModifiers };
101
+ }
102
+ function applyCharModifiers(char, mods) {
103
+ let value = char;
104
+ if (mods.shift && value.length === 1 && /[a-z]/.test(value)) {
105
+ value = value.toUpperCase();
106
+ }
107
+ if (mods.ctrl) {
108
+ const ctrl = toCtrlChar(value);
109
+ if (ctrl)
110
+ value = ctrl;
111
+ }
112
+ if (mods.alt) {
113
+ value = `${ESC}${value}`;
114
+ }
115
+ return value;
116
+ }
117
+ function toCtrlChar(char) {
118
+ if (char.length !== 1)
119
+ return null;
120
+ if (char === "?")
121
+ return "\x7f";
122
+ const code = char.toUpperCase().charCodeAt(0);
123
+ if (code >= 64 && code <= 95) {
124
+ return String.fromCharCode(code & 0x1f);
125
+ }
126
+ return null;
127
+ }
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+ export declare const RUNTIME_STARTUP_PREFIX = "SYNERGY_STARTUP_V1 ";
3
+ export declare const RUNTIME_STARTUP_MAX_LINE_LENGTH = 1024;
4
+ export declare const RuntimeStartupProgress: z.ZodDiscriminatedUnion<[z.ZodObject<{
5
+ phase: z.ZodLiteral<"starting">;
6
+ }, z.core.$strict>, z.ZodObject<{
7
+ phase: z.ZodLiteral<"recovery">;
8
+ current: z.ZodNumber;
9
+ }, z.core.$strict>, z.ZodObject<{
10
+ phase: z.ZodLiteral<"migration">;
11
+ step: z.ZodNumber;
12
+ current: z.ZodNumber;
13
+ total: z.ZodNumber;
14
+ }, z.core.$strict>], "phase">;
15
+ export type RuntimeStartupProgress = z.infer<typeof RuntimeStartupProgress>;
16
+ export declare function runtimeStartupLine(progress: RuntimeStartupProgress): string;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ export const RUNTIME_STARTUP_PREFIX = "SYNERGY_STARTUP_V1 ";
3
+ export const RUNTIME_STARTUP_MAX_LINE_LENGTH = 1024;
4
+ const count = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
5
+ export const RuntimeStartupProgress = z.discriminatedUnion("phase", [
6
+ z.object({ phase: z.literal("starting") }).strict(),
7
+ z.object({ phase: z.literal("recovery"), current: count }).strict(),
8
+ z
9
+ .object({
10
+ phase: z.literal("migration"),
11
+ step: count.positive(),
12
+ current: count,
13
+ total: count,
14
+ })
15
+ .strict()
16
+ .refine((value) => value.current <= value.total),
17
+ ]);
18
+ export function runtimeStartupLine(progress) {
19
+ return RUNTIME_STARTUP_PREFIX + JSON.stringify(RuntimeStartupProgress.parse(progress)) + "\n";
20
+ }
@@ -0,0 +1,4 @@
1
+ export interface SettingCondition {
2
+ setting: string;
3
+ equals: string | number | boolean;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ export type ShellFunction = (input: Uint8Array) => Uint8Array;
2
+ export type ShellExpression = {
3
+ toString(): string;
4
+ } | Array<ShellExpression> | string | {
5
+ raw: string;
6
+ } | ReadableStream;
7
+ export interface BunShell {
8
+ (strings: TemplateStringsArray, ...expressions: ShellExpression[]): BunShellPromise;
9
+ /**
10
+ * Perform bash-like brace expansion on the given pattern.
11
+ * @param pattern - Brace pattern to expand
12
+ */
13
+ braces(pattern: string): string[];
14
+ /**
15
+ * Escape strings for input into shell commands.
16
+ */
17
+ escape(input: string): string;
18
+ /**
19
+ * Change the default environment variables for shells created by this instance.
20
+ */
21
+ env(newEnv?: Record<string, string | undefined>): BunShell;
22
+ /**
23
+ * Default working directory to use for shells created by this instance.
24
+ */
25
+ cwd(newCwd?: string): BunShell;
26
+ /**
27
+ * Configure the shell to not throw an exception on non-zero exit codes.
28
+ */
29
+ nothrow(): BunShell;
30
+ /**
31
+ * Configure whether or not the shell should throw an exception on non-zero exit codes.
32
+ */
33
+ throws(shouldThrow: boolean): BunShell;
34
+ }
35
+ export interface BunShellPromise extends Promise<BunShellOutput> {
36
+ readonly stdin: WritableStream;
37
+ /**
38
+ * Change the current working directory of the shell.
39
+ */
40
+ cwd(newCwd: string): this;
41
+ /**
42
+ * Set environment variables for the shell.
43
+ */
44
+ env(newEnv: Record<string, string> | undefined): this;
45
+ /**
46
+ * By default, the shell will write to the current process's stdout and stderr, as well as buffering that output.
47
+ * This configures the shell to only buffer the output.
48
+ */
49
+ quiet(): this;
50
+ /**
51
+ * Read from stdout as a string, line by line
52
+ * Automatically calls quiet() to disable echoing to stdout.
53
+ */
54
+ lines(): AsyncIterable<string>;
55
+ /**
56
+ * Read from stdout as a string.
57
+ * Automatically calls quiet() to disable echoing to stdout.
58
+ */
59
+ text(encoding?: BufferEncoding): Promise<string>;
60
+ /**
61
+ * Read from stdout as a JSON object
62
+ * Automatically calls quiet()
63
+ */
64
+ json(): Promise<any>;
65
+ /**
66
+ * Read from stdout as an ArrayBuffer
67
+ * Automatically calls quiet()
68
+ */
69
+ arrayBuffer(): Promise<ArrayBuffer>;
70
+ /**
71
+ * Read from stdout as a Blob
72
+ * Automatically calls quiet()
73
+ */
74
+ blob(): Promise<Blob>;
75
+ /**
76
+ * Configure the shell to not throw an exception on non-zero exit codes.
77
+ */
78
+ nothrow(): this;
79
+ /**
80
+ * Configure whether or not the shell should throw an exception on non-zero exit codes.
81
+ */
82
+ throws(shouldThrow: boolean): this;
83
+ }
84
+ export interface BunShellOutput {
85
+ readonly stdout: Buffer;
86
+ readonly stderr: Buffer;
87
+ readonly exitCode: number;
88
+ /**
89
+ * Read from stdout as a string
90
+ */
91
+ text(encoding?: BufferEncoding): string;
92
+ /**
93
+ * Read from stdout as a JSON object
94
+ */
95
+ json(): any;
96
+ /**
97
+ * Read from stdout as an ArrayBuffer
98
+ */
99
+ arrayBuffer(): ArrayBuffer;
100
+ /**
101
+ * Read from stdout as an Uint8Array
102
+ */
103
+ bytes(): Uint8Array;
104
+ /**
105
+ * Read from stdout as a Blob
106
+ */
107
+ blob(): Blob;
108
+ }
109
+ export type BunShellError = Error & BunShellOutput;
package/dist/shell.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ export interface ToolMediaDisplay {
2
+ type: "image" | "video" | "audio";
3
+ actionLabel?: string;
4
+ pendingTitle?: string;
5
+ pendingDescription?: string;
6
+ aspectRatio?: "1:1" | "4:3" | "16:9" | "auto";
7
+ size?: "small" | "medium" | "large";
8
+ }
9
+ export interface ToolDisplay {
10
+ kind?: "default" | "media-generation";
11
+ toolCard?: "visible" | "hidden";
12
+ media?: ToolMediaDisplay;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/tool.d.ts ADDED
@@ -0,0 +1,146 @@
1
+ import { z } from "zod";
2
+ import type { ToolDisplay } from "./tool-display.js";
3
+ import type { BunShell } from "./shell.js";
4
+ export type { ToolDisplay, ToolMediaDisplay } from "./tool-display.js";
5
+ export type ToolContext = {
6
+ sessionID: string;
7
+ messageID: string;
8
+ agent: string;
9
+ abort: AbortSignal;
10
+ directory?: string;
11
+ /** Request permission from the user before proceeding */
12
+ ask?(input: {
13
+ permission: string;
14
+ patterns: string[];
15
+ metadata?: Record<string, any>;
16
+ }): Promise<void>;
17
+ /** Run shell commands through Synergy's current workspace shell boundary. */
18
+ $?: BunShell;
19
+ /** Run a Synergy delegated subagent task from inside this tool. */
20
+ task?: ToolTaskService;
21
+ /** Invoke another visible/explicitly-allowed Synergy tool from inside this tool. */
22
+ tools?: ToolInvokeService;
23
+ };
24
+ export type ToolTaskVisibility = "visible" | "hidden";
25
+ export type ToolTaskOutput = {
26
+ mode?: "summary";
27
+ } | {
28
+ mode: "final_response";
29
+ } | {
30
+ mode: "structured";
31
+ schema: Record<string, unknown>;
32
+ maxRepairTurns?: 0 | 1 | 2 | 3;
33
+ };
34
+ export type ToolTaskRunOutput = {
35
+ mode: "summary";
36
+ value: string;
37
+ } | {
38
+ mode: "final_response";
39
+ value: string;
40
+ } | {
41
+ mode: "structured";
42
+ value: unknown;
43
+ };
44
+ export interface ToolTaskRunInput {
45
+ subagent: string;
46
+ description: string;
47
+ prompt: string;
48
+ tools?: Record<string, boolean>;
49
+ visibility?: ToolTaskVisibility;
50
+ timeoutMs?: number;
51
+ output?: ToolTaskOutput;
52
+ category?: string;
53
+ model?: {
54
+ providerID: string;
55
+ modelID: string;
56
+ };
57
+ }
58
+ export interface ToolTaskRunResult {
59
+ taskId: string;
60
+ sessionId: string;
61
+ status: "completed" | "error" | "cancelled" | "timeout";
62
+ output?: ToolTaskRunOutput;
63
+ error?: string;
64
+ }
65
+ export interface ToolTaskService {
66
+ run(input: ToolTaskRunInput): Promise<ToolTaskRunResult>;
67
+ }
68
+ export interface ToolInvokeInput {
69
+ tool: string;
70
+ args?: unknown;
71
+ timeoutMs?: number;
72
+ }
73
+ export interface ToolInvokeService {
74
+ invoke(input: ToolInvokeInput): Promise<ToolResult>;
75
+ }
76
+ export type ToolResultMetadata = Record<string, any> & {
77
+ display?: ToolDisplay;
78
+ };
79
+ export type PluginToolAttachment = {
80
+ type: "attachment";
81
+ id: string;
82
+ sessionID: string;
83
+ messageID: string;
84
+ mime: string;
85
+ filename?: string;
86
+ url: string;
87
+ localPath?: string;
88
+ presentation?: {
89
+ hidden?: boolean;
90
+ renderer?: "image" | "video" | "audio" | "thumbnail" | "file";
91
+ size?: "original" | "small" | "medium" | "large";
92
+ crop?: boolean;
93
+ };
94
+ model?: {
95
+ mode: "summary";
96
+ summary?: string;
97
+ } | {
98
+ mode: "content";
99
+ text?: string;
100
+ } | {
101
+ mode: "provider-file";
102
+ summary?: string;
103
+ } | {
104
+ mode: "none";
105
+ };
106
+ metadata?: Record<string, any>;
107
+ };
108
+ export interface ToolResult {
109
+ title?: string;
110
+ output: string;
111
+ metadata?: ToolResultMetadata;
112
+ attachments?: PluginToolAttachment[];
113
+ }
114
+ export type PluginToolResult = ToolResult;
115
+ export type ToolExposure = {
116
+ mode: "resident";
117
+ } | {
118
+ mode: "group";
119
+ group: string;
120
+ title?: string;
121
+ description?: string;
122
+ whenToExpand?: string;
123
+ } | {
124
+ mode: "search";
125
+ title?: string;
126
+ keywords?: string[];
127
+ } | {
128
+ mode: "internal";
129
+ };
130
+ export declare function tool<Args extends z.ZodRawShape>(input: {
131
+ description: string;
132
+ exposure?: ToolExposure;
133
+ display?: ToolDisplay;
134
+ args: Args;
135
+ execute(args: z.infer<z.ZodObject<Args>>, context: ToolContext): Promise<string | ToolResult>;
136
+ }): {
137
+ description: string;
138
+ exposure?: ToolExposure;
139
+ display?: ToolDisplay;
140
+ args: Args;
141
+ execute(args: z.infer<z.ZodObject<Args>>, context: ToolContext): Promise<string | ToolResult>;
142
+ };
143
+ export declare namespace tool {
144
+ var schema: typeof z;
145
+ }
146
+ export type ToolDefinition = ReturnType<typeof tool>;
package/dist/tool.js ADDED
@@ -0,0 +1,5 @@
1
+ import { z } from "zod";
2
+ export function tool(input) {
3
+ return input;
4
+ }
5
+ tool.schema = z;
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@ericsanchezok/synergy-util",
3
- "version": "3.0.22",
3
+ "version": "3.0.23",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  "./*": {
8
8
  "types": "./dist/*.d.ts",
9
9
  "import": "./dist/*.js"
10
+ },
11
+ "./pty-keys": {
12
+ "types": "./dist/pty-keys.d.ts",
13
+ "import": "./dist/pty-keys.js"
10
14
  }
11
15
  },
12
16
  "scripts": {