@beeos-ai/device-agent 0.4.2 → 0.5.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.
- package/.pi/extensions/android-tools.ts +146 -15
- package/LICENSE +201 -0
- package/dist/adapters/agent-gateway-client.d.ts +37 -0
- package/dist/adapters/agent-gateway-client.js +45 -0
- package/dist/adapters/agent-gateway-client.js.map +1 -1
- package/dist/adapters/agentcore-pi.d.ts +22 -0
- package/dist/adapters/agentcore-pi.js +48 -0
- package/dist/adapters/agentcore-pi.js.map +1 -1
- package/dist/adapters/device-android-adb.d.ts +47 -0
- package/dist/adapters/device-android-adb.js +50 -0
- package/dist/adapters/device-android-adb.js.map +1 -1
- package/dist/adapters/device-desktop.d.ts +12 -0
- package/dist/adapters/device-desktop.js +31 -0
- package/dist/adapters/device-desktop.js.map +1 -1
- package/dist/agent-runtime/adapters/base.d.ts +20 -0
- package/dist/agent-runtime/adapters/base.js.map +1 -1
- package/dist/agent-runtime/agent-runner.d.ts +4 -2
- package/dist/agent-runtime/agent-runner.js.map +1 -1
- package/dist/agent-runtime/core.d.ts +60 -0
- package/dist/agent-runtime/core.js +190 -9
- package/dist/agent-runtime/core.js.map +1 -1
- package/dist/agent-runtime/feedback.d.ts +56 -0
- package/dist/agent-runtime/feedback.js +54 -0
- package/dist/agent-runtime/feedback.js.map +1 -0
- package/dist/agent-runtime/index.d.ts +1 -0
- package/dist/agent-runtime/index.js +1 -0
- package/dist/agent-runtime/index.js.map +1 -1
- package/dist/agent-runtime/plan-executor.js +24 -0
- package/dist/agent-runtime/plan-executor.js.map +1 -1
- package/dist/agent-runtime/planner/base.d.ts +10 -0
- package/dist/agent-runtime/planner/base.js.map +1 -1
- package/dist/agent-runtime/planner/llm-planner.js +1 -0
- package/dist/agent-runtime/planner/llm-planner.js.map +1 -1
- package/dist/agent-runtime/planner/prompts.d.ts +3 -0
- package/dist/agent-runtime/planner/prompts.js +12 -0
- package/dist/agent-runtime/planner/prompts.js.map +1 -1
- package/dist/agent-runtime/reflection.d.ts +25 -6
- package/dist/agent-runtime/reflection.js +64 -22
- package/dist/agent-runtime/reflection.js.map +1 -1
- package/dist/agent-runtime/reflectors/policy.d.ts +10 -4
- package/dist/agent-runtime/reflectors/policy.js +19 -6
- package/dist/agent-runtime/reflectors/policy.js.map +1 -1
- package/dist/agent-runtime/shortcuts/fs-store.d.ts +41 -0
- package/dist/agent-runtime/shortcuts/fs-store.js +122 -0
- package/dist/agent-runtime/shortcuts/fs-store.js.map +1 -0
- package/dist/agent-runtime/shortcuts/in-memory-store.d.ts +20 -0
- package/dist/agent-runtime/shortcuts/in-memory-store.js +64 -0
- package/dist/agent-runtime/shortcuts/in-memory-store.js.map +1 -0
- package/dist/agent-runtime/shortcuts/index.d.ts +10 -0
- package/dist/agent-runtime/shortcuts/index.js +10 -0
- package/dist/agent-runtime/shortcuts/index.js.map +1 -0
- package/dist/agent-runtime/shortcuts/types.d.ts +69 -0
- package/dist/agent-runtime/shortcuts/types.js +17 -0
- package/dist/agent-runtime/shortcuts/types.js.map +1 -0
- package/dist/app/agent-host.d.ts +83 -0
- package/dist/app/agent-host.js +345 -32
- package/dist/app/agent-host.js.map +1 -1
- package/dist/app/session-manager.d.ts +33 -4
- package/dist/app/session-manager.js +27 -5
- package/dist/app/session-manager.js.map +1 -1
- package/dist/bootstrap.js +187 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/config/loader.js +22 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +118 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/inbound/acp/handlers/session.js.map +1 -1
- package/dist/mcp-client/client.d.ts +6 -0
- package/dist/mcp-client/client.js +11 -0
- package/dist/mcp-client/client.js.map +1 -1
- package/dist/mcp-client/runtime.d.ts +13 -0
- package/dist/orchestrator-system-prompt.d.ts +26 -0
- package/dist/orchestrator-system-prompt.js +118 -2
- package/dist/orchestrator-system-prompt.js.map +1 -1
- package/dist/pi-context.d.ts +50 -0
- package/dist/pi-context.js.map +1 -1
- package/dist/ports/device.d.ts +18 -0
- package/dist/resources/augmenter.d.ts +48 -0
- package/dist/resources/augmenter.js +126 -0
- package/dist/resources/augmenter.js.map +1 -0
- package/dist/resources/cache.d.ts +57 -0
- package/dist/resources/cache.js +107 -0
- package/dist/resources/cache.js.map +1 -0
- package/dist/resources/index.d.ts +17 -0
- package/dist/resources/index.js +15 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/lifecycle/disk-pressure.d.ts +75 -0
- package/dist/resources/lifecycle/disk-pressure.js +148 -0
- package/dist/resources/lifecycle/disk-pressure.js.map +1 -0
- package/dist/resources/lifecycle/index.d.ts +7 -0
- package/dist/resources/lifecycle/index.js +7 -0
- package/dist/resources/lifecycle/index.js.map +1 -0
- package/dist/resources/lifecycle/manager.d.ts +38 -0
- package/dist/resources/lifecycle/manager.js +205 -0
- package/dist/resources/lifecycle/manager.js.map +1 -0
- package/dist/resources/lifecycle/sweeper.d.ts +36 -0
- package/dist/resources/lifecycle/sweeper.js +179 -0
- package/dist/resources/lifecycle/sweeper.js.map +1 -0
- package/dist/resources/lifecycle/types.d.ts +180 -0
- package/dist/resources/lifecycle/types.js +46 -0
- package/dist/resources/lifecycle/types.js.map +1 -0
- package/dist/resources/parsers.d.ts +28 -0
- package/dist/resources/parsers.js +88 -0
- package/dist/resources/parsers.js.map +1 -0
- package/dist/resources/registry.d.ts +47 -0
- package/dist/resources/registry.js +107 -0
- package/dist/resources/registry.js.map +1 -0
- package/dist/resources/resolvers/beeos-file-resolver.d.ts +62 -0
- package/dist/resources/resolvers/beeos-file-resolver.js +109 -0
- package/dist/resources/resolvers/beeos-file-resolver.js.map +1 -0
- package/dist/resources/resolvers/errors.d.ts +11 -0
- package/dist/resources/resolvers/errors.js +23 -0
- package/dist/resources/resolvers/errors.js.map +1 -0
- package/dist/resources/resolvers/mime-table.d.ts +41 -0
- package/dist/resources/resolvers/mime-table.js +92 -0
- package/dist/resources/resolvers/mime-table.js.map +1 -0
- package/dist/resources/resolvers/url-resolver.d.ts +85 -0
- package/dist/resources/resolvers/url-resolver.js +495 -0
- package/dist/resources/resolvers/url-resolver.js.map +1 -0
- package/dist/resources/shortcut-facade.d.ts +51 -0
- package/dist/resources/shortcut-facade.js +72 -0
- package/dist/resources/shortcut-facade.js.map +1 -0
- package/dist/resources/telemetry.d.ts +52 -0
- package/dist/resources/telemetry.js +59 -0
- package/dist/resources/telemetry.js.map +1 -0
- package/dist/resources/types.d.ts +249 -0
- package/dist/resources/types.js +29 -0
- package/dist/resources/types.js.map +1 -0
- package/dist/shortcuts/builtins/download-to-device.d.ts +83 -0
- package/dist/shortcuts/builtins/download-to-device.js +125 -0
- package/dist/shortcuts/builtins/download-to-device.js.map +1 -0
- package/dist/shortcuts/builtins/find-app-package.d.ts +79 -0
- package/dist/shortcuts/builtins/find-app-package.js +168 -0
- package/dist/shortcuts/builtins/find-app-package.js.map +1 -0
- package/dist/shortcuts/builtins/index.d.ts +32 -0
- package/dist/shortcuts/builtins/index.js +37 -0
- package/dist/shortcuts/builtins/index.js.map +1 -0
- package/dist/shortcuts/builtins/open-deeplink.d.ts +68 -0
- package/dist/shortcuts/builtins/open-deeplink.js +142 -0
- package/dist/shortcuts/builtins/open-deeplink.js.map +1 -0
- package/dist/shortcuts/builtins/set-clipboard.d.ts +65 -0
- package/dist/shortcuts/builtins/set-clipboard.js +112 -0
- package/dist/shortcuts/builtins/set-clipboard.js.map +1 -0
- package/dist/shortcuts/index.d.ts +11 -0
- package/dist/shortcuts/index.js +11 -0
- package/dist/shortcuts/index.js.map +1 -0
- package/dist/shortcuts/registry.d.ts +56 -0
- package/dist/shortcuts/registry.js +70 -0
- package/dist/shortcuts/registry.js.map +1 -0
- package/dist/shortcuts/router.d.ts +91 -0
- package/dist/shortcuts/router.js +158 -0
- package/dist/shortcuts/router.js.map +1 -0
- package/dist/shortcuts/types.d.ts +219 -0
- package/dist/shortcuts/types.js +46 -0
- package/dist/shortcuts/types.js.map +1 -0
- package/package.json +24 -25
- package/dist/agent-runtime/skills/sqlite-store.d.ts +0 -60
- package/dist/agent-runtime/skills/sqlite-store.js +0 -234
- package/dist/agent-runtime/skills/sqlite-store.js.map +0 -1
- package/dist/test-lan-autoglm.d.ts +0 -7
- package/dist/test-lan-autoglm.js +0 -46
- package/dist/test-lan-autoglm.js.map +0 -1
- package/dist/test-mem-breakdown.d.ts +0 -1
- package/dist/test-mem-breakdown.js +0 -103
- package/dist/test-mem-breakdown.js.map +0 -1
- package/dist/test-mem.d.ts +0 -1
- package/dist/test-mem.js +0 -60
- package/dist/test-mem.js.map +0 -1
- package/dist/test-mobile-use.d.ts +0 -1
- package/dist/test-mobile-use.js +0 -18
- package/dist/test-mobile-use.js.map +0 -1
- package/dist/test-screenshot-loop.d.ts +0 -1
- package/dist/test-screenshot-loop.js +0 -43
- package/dist/test-screenshot-loop.js.map +0 -1
- package/dist/test-screenshot.d.ts +0 -1
- package/dist/test-screenshot.js +0 -10
- package/dist/test-screenshot.js.map +0 -1
- package/dist/test-ui-xml-dump.d.ts +0 -15
- package/dist/test-ui-xml-dump.js +0 -49
- package/dist/test-ui-xml-dump.js.map +0 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortcut: `set_clipboard`
|
|
3
|
+
*
|
|
4
|
+
* Set the device clipboard contents to a caller-supplied string.
|
|
5
|
+
*
|
|
6
|
+
* Why a shortcut:
|
|
7
|
+
*
|
|
8
|
+
* The GUI-only VLM cannot type long strings reliably (especially
|
|
9
|
+
* non-Latin scripts and emoji), and the legacy `apply({kind:"type"})`
|
|
10
|
+
* path piggybacks on the IME — which on most ROMs strips zero-width
|
|
11
|
+
* characters and re-encodes emoji. The shortcut bypasses both
|
|
12
|
+
* problems by placing the text on the system clipboard via the ADB
|
|
13
|
+
* Keyboard input method's broadcast hook
|
|
14
|
+
* (`ime.adb.android.ADB_INPUT_TEXT`); the VLM's later
|
|
15
|
+
* long-press → "粘贴 / Paste" works against bit-exact text.
|
|
16
|
+
*
|
|
17
|
+
* Compatibility note:
|
|
18
|
+
*
|
|
19
|
+
* ADBKeyboard (com.android.adbkeyboard) must be the active IME for
|
|
20
|
+
* the broadcast to take effect. On stock ROMs the user / agent
|
|
21
|
+
* needs to install + select it once. When the broadcast is dropped
|
|
22
|
+
* silently (no error code from `am`), the shortcut still returns
|
|
23
|
+
* `ok: true` because there is no observable failure mode short of
|
|
24
|
+
* reading the clipboard back. A future Phase-3 verification step
|
|
25
|
+
* may add a clipboard read-back via `cmd clipboard get-text`, but
|
|
26
|
+
* per D5 we don't gate on it now.
|
|
27
|
+
*
|
|
28
|
+
* Platform: Android only. Desktop has no equivalent ADB-keyboard
|
|
29
|
+
* primitive; calling the shortcut on a desktop device returns
|
|
30
|
+
* `unsupported_platform` from the router's platform gate.
|
|
31
|
+
*
|
|
32
|
+
* Telemetry: `shortcut.invoke` log line; counter dimension
|
|
33
|
+
* `shortcut_id="set_clipboard"`.
|
|
34
|
+
*/
|
|
35
|
+
const MAX_TEXT_LEN = 50_000;
|
|
36
|
+
export class SetClipboardShortcut {
|
|
37
|
+
descriptor = {
|
|
38
|
+
id: "set_clipboard",
|
|
39
|
+
displayName: "Set Clipboard",
|
|
40
|
+
description: "Place arbitrary text (including non-Latin scripts and emoji) on " +
|
|
41
|
+
"the Android device's clipboard. The VLM can paste it later via " +
|
|
42
|
+
"long-press. Use this for any long / exotic text input that the " +
|
|
43
|
+
"GUI keyboard would mangle. Requires ADBKeyboard IME to be the " +
|
|
44
|
+
"active input method on the device.",
|
|
45
|
+
jsonSchema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: {
|
|
48
|
+
text: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Verbatim text to place on the clipboard. Up to 50,000 chars.",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
required: ["text"],
|
|
54
|
+
additionalProperties: false,
|
|
55
|
+
},
|
|
56
|
+
kind: "api",
|
|
57
|
+
platforms: ["android"],
|
|
58
|
+
timeoutMs: 5_000,
|
|
59
|
+
};
|
|
60
|
+
async execute(args, ctx) {
|
|
61
|
+
if (typeof args?.text !== "string") {
|
|
62
|
+
return { ok: false, code: "invalid_args", message: "text must be a string" };
|
|
63
|
+
}
|
|
64
|
+
if (args.text.length > MAX_TEXT_LEN) {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
code: "invalid_args",
|
|
68
|
+
message: `text exceeds ${MAX_TEXT_LEN} chars`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (!ctx.mcp || typeof ctx.mcp.executeCommand !== "function") {
|
|
72
|
+
return {
|
|
73
|
+
ok: false,
|
|
74
|
+
code: "permission_denied",
|
|
75
|
+
message: "active MCP runtime cannot execute shell commands",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Encode text → base64 so single-quote / newline / shell escape
|
|
79
|
+
// hazards never reach `am broadcast`. ADBKeyboard accepts the
|
|
80
|
+
// base64 form via `--es msg <b64>` paired with `--ei type 1`
|
|
81
|
+
// (1 = base64 input).
|
|
82
|
+
const b64 = Buffer.from(args.text, "utf8").toString("base64");
|
|
83
|
+
const cmd = `am broadcast -a ADB_INPUT_B64 --es msg ${shellQuote(b64)}`;
|
|
84
|
+
try {
|
|
85
|
+
const res = await ctx.mcp.executeCommand(cmd, { timeoutS: 4 });
|
|
86
|
+
if (res.exitCode !== 0) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
code: "intent_rejected",
|
|
90
|
+
message: `am broadcast exit=${res.exitCode}: ${res.stderr.trim() || res.stdout.trim()}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
return {
|
|
96
|
+
ok: false,
|
|
97
|
+
code: "internal_error",
|
|
98
|
+
message: e.message,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return { ok: true, output: { length: args.text.length } };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Quote `s` for safe inclusion in a single-quoted shell argument.
|
|
106
|
+
* The string is base64-encoded ASCII (no quotes possible) but we keep
|
|
107
|
+
* the quoting defensively in case the encoder ever changes.
|
|
108
|
+
*/
|
|
109
|
+
function shellQuote(s) {
|
|
110
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=set-clipboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-clipboard.js","sourceRoot":"","sources":["../../../src/shortcuts/builtins/set-clipboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,MAAM,YAAY,GAAG,MAAM,CAAC;AAE5B,MAAM,OAAO,oBAAoB;IACtB,UAAU,GAAG;QACpB,EAAE,EAAE,eAAe;QACnB,WAAW,EAAE,eAAe;QAC5B,WAAW,EACT,kEAAkE;YAClE,iEAAiE;YACjE,iEAAiE;YACjE,gEAAgE;YAChE,oCAAoC;QACtC,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8DAA8D;iBAC5E;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClB,oBAAoB,EAAE,KAAK;SAC5B;QACD,IAAI,EAAE,KAAc;QACpB,SAAS,EAAE,CAAC,SAAS,CAAU;QAC/B,SAAS,EAAE,KAAK;KACjB,CAAC;IAEF,KAAK,CAAC,OAAO,CACX,IAAsB,EACtB,GAAoB;QAEpB,IAAI,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;QAC/E,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;YACpC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,gBAAgB,YAAY,QAAQ;aAC9C,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;YAC7D,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,kDAAkD;aAC5D,CAAC;QACJ,CAAC;QAED,gEAAgE;QAChE,8DAA8D;QAC9D,6DAA6D;QAC7D,sBAAsB;QACtB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,GAAG,GACP,0CAA0C,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAE9D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/D,IAAI,GAAG,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,IAAI,EAAE,iBAAiB;oBACvB,OAAO,EACL,qBAAqB,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE;iBACjF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAG,CAAW,CAAC,OAAO;aAC9B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;IAC5D,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shortcuts/ — Hybrid Action Space barrel.
|
|
3
|
+
*
|
|
4
|
+
* Public surface for Phase 2 of the GUI-Shortcut Hybrid Plan. Mirrors
|
|
5
|
+
* the structure of `resources/index.ts` so callers reach for one
|
|
6
|
+
* import path and don't have to spelunk into the submodules.
|
|
7
|
+
*/
|
|
8
|
+
export type { Shortcut, ShortcutContext, ShortcutDescriptor, ShortcutDeviceFacade, ShortcutErrorCode, ShortcutFailure, ShortcutJsonSchema, ShortcutKind, ShortcutLogger, ShortcutMcpRuntime, ShortcutPlatform, ShortcutResourceFacade, ShortcutResult, ShortcutSuccess, } from "./types.js";
|
|
9
|
+
export { ShortcutRegistry } from "./registry.js";
|
|
10
|
+
export { ShortcutRouter, type InvokeCallerContext, type ShortcutInvoker, } from "./router.js";
|
|
11
|
+
export { DownloadToDeviceShortcut, FindAppPackageShortcut, OpenDeeplinkShortcut, SetClipboardShortcut, registerBuiltinShortcuts, } from "./builtins/index.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shortcuts/ — Hybrid Action Space barrel.
|
|
3
|
+
*
|
|
4
|
+
* Public surface for Phase 2 of the GUI-Shortcut Hybrid Plan. Mirrors
|
|
5
|
+
* the structure of `resources/index.ts` so callers reach for one
|
|
6
|
+
* import path and don't have to spelunk into the submodules.
|
|
7
|
+
*/
|
|
8
|
+
export { ShortcutRegistry } from "./registry.js";
|
|
9
|
+
export { ShortcutRouter, } from "./router.js";
|
|
10
|
+
export { DownloadToDeviceShortcut, FindAppPackageShortcut, OpenDeeplinkShortcut, SetClipboardShortcut, registerBuiltinShortcuts, } from "./builtins/index.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shortcuts/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,cAAc,GAGf,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortcut registry — owns the in-process catalogue of shortcuts.
|
|
3
|
+
*
|
|
4
|
+
* The registry is intentionally tiny: register / unregister / list /
|
|
5
|
+
* get. There is no recall yet (D7) — the .pi extension reads `list()`
|
|
6
|
+
* once at session start and synthesises an outer-LLM tool descriptor
|
|
7
|
+
* for every entry.
|
|
8
|
+
*
|
|
9
|
+
* Lifecycle:
|
|
10
|
+
* 1. Bootstrap constructs ONE registry per device-agent process.
|
|
11
|
+
* 2. Each phase-2 shortcut module exports a `register(reg)` helper
|
|
12
|
+
* that calls `reg.register(new MyShortcut())`. Bootstrap fans out
|
|
13
|
+
* to every helper so adding a shortcut is one import + one
|
|
14
|
+
* register call away.
|
|
15
|
+
* 3. The .pi extension reads `reg.list()` and emits descriptors.
|
|
16
|
+
* 4. The router (`router.ts`) calls `reg.get(id)` on every invoke.
|
|
17
|
+
*
|
|
18
|
+
* Recall seam:
|
|
19
|
+
*
|
|
20
|
+
* `recallCandidates(taskHint)` is a no-op stub that returns the full
|
|
21
|
+
* list. Phase 3+ can swap the implementation for a real recall (e.g.
|
|
22
|
+
* embedding similarity over `descriptor.description`) without
|
|
23
|
+
* touching call sites.
|
|
24
|
+
*/
|
|
25
|
+
import type { Shortcut } from "./types.js";
|
|
26
|
+
export declare class ShortcutRegistry {
|
|
27
|
+
private readonly entries;
|
|
28
|
+
/**
|
|
29
|
+
* Register a shortcut. Throws on duplicate id — duplicate registrations
|
|
30
|
+
* almost always indicate a bootstrap-ordering bug, and the registry
|
|
31
|
+
* is process-wide so silent overwrites would be invisible.
|
|
32
|
+
*/
|
|
33
|
+
register<TArgs, TOut>(shortcut: Shortcut<TArgs, TOut>): void;
|
|
34
|
+
/**
|
|
35
|
+
* Remove a shortcut by id. Returns true if the id existed. Mostly
|
|
36
|
+
* used in tests; the production process never tears shortcuts down.
|
|
37
|
+
*/
|
|
38
|
+
unregister(id: string): boolean;
|
|
39
|
+
/** Look up a shortcut by id. Undefined when missing. */
|
|
40
|
+
get(id: string): Shortcut<unknown, unknown> | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Return every registered shortcut in insertion order. The .pi
|
|
43
|
+
* extension uses this for tool-descriptor generation; tests use it
|
|
44
|
+
* for snapshot assertions. The returned array is a copy so callers
|
|
45
|
+
* are free to filter / sort / iterate without disturbing the
|
|
46
|
+
* registry's internal map.
|
|
47
|
+
*/
|
|
48
|
+
list(): Shortcut<unknown, unknown>[];
|
|
49
|
+
/**
|
|
50
|
+
* Future recall hook. Phase 2 returns the full list verbatim — the
|
|
51
|
+
* orchestrator gets every shortcut every time, which is fine at 4
|
|
52
|
+
* entries (D7). Phase 3+ may implement a real recall by replacing
|
|
53
|
+
* this implementation; downstream code never has to change.
|
|
54
|
+
*/
|
|
55
|
+
recallCandidates(_taskHint?: string): Shortcut<unknown, unknown>[];
|
|
56
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortcut registry — owns the in-process catalogue of shortcuts.
|
|
3
|
+
*
|
|
4
|
+
* The registry is intentionally tiny: register / unregister / list /
|
|
5
|
+
* get. There is no recall yet (D7) — the .pi extension reads `list()`
|
|
6
|
+
* once at session start and synthesises an outer-LLM tool descriptor
|
|
7
|
+
* for every entry.
|
|
8
|
+
*
|
|
9
|
+
* Lifecycle:
|
|
10
|
+
* 1. Bootstrap constructs ONE registry per device-agent process.
|
|
11
|
+
* 2. Each phase-2 shortcut module exports a `register(reg)` helper
|
|
12
|
+
* that calls `reg.register(new MyShortcut())`. Bootstrap fans out
|
|
13
|
+
* to every helper so adding a shortcut is one import + one
|
|
14
|
+
* register call away.
|
|
15
|
+
* 3. The .pi extension reads `reg.list()` and emits descriptors.
|
|
16
|
+
* 4. The router (`router.ts`) calls `reg.get(id)` on every invoke.
|
|
17
|
+
*
|
|
18
|
+
* Recall seam:
|
|
19
|
+
*
|
|
20
|
+
* `recallCandidates(taskHint)` is a no-op stub that returns the full
|
|
21
|
+
* list. Phase 3+ can swap the implementation for a real recall (e.g.
|
|
22
|
+
* embedding similarity over `descriptor.description`) without
|
|
23
|
+
* touching call sites.
|
|
24
|
+
*/
|
|
25
|
+
export class ShortcutRegistry {
|
|
26
|
+
entries = new Map();
|
|
27
|
+
/**
|
|
28
|
+
* Register a shortcut. Throws on duplicate id — duplicate registrations
|
|
29
|
+
* almost always indicate a bootstrap-ordering bug, and the registry
|
|
30
|
+
* is process-wide so silent overwrites would be invisible.
|
|
31
|
+
*/
|
|
32
|
+
register(shortcut) {
|
|
33
|
+
const id = shortcut.descriptor.id;
|
|
34
|
+
if (this.entries.has(id)) {
|
|
35
|
+
throw new Error(`ShortcutRegistry: duplicate shortcut id "${id}" — already registered`);
|
|
36
|
+
}
|
|
37
|
+
this.entries.set(id, shortcut);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Remove a shortcut by id. Returns true if the id existed. Mostly
|
|
41
|
+
* used in tests; the production process never tears shortcuts down.
|
|
42
|
+
*/
|
|
43
|
+
unregister(id) {
|
|
44
|
+
return this.entries.delete(id);
|
|
45
|
+
}
|
|
46
|
+
/** Look up a shortcut by id. Undefined when missing. */
|
|
47
|
+
get(id) {
|
|
48
|
+
return this.entries.get(id);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Return every registered shortcut in insertion order. The .pi
|
|
52
|
+
* extension uses this for tool-descriptor generation; tests use it
|
|
53
|
+
* for snapshot assertions. The returned array is a copy so callers
|
|
54
|
+
* are free to filter / sort / iterate without disturbing the
|
|
55
|
+
* registry's internal map.
|
|
56
|
+
*/
|
|
57
|
+
list() {
|
|
58
|
+
return Array.from(this.entries.values());
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Future recall hook. Phase 2 returns the full list verbatim — the
|
|
62
|
+
* orchestrator gets every shortcut every time, which is fine at 4
|
|
63
|
+
* entries (D7). Phase 3+ may implement a real recall by replacing
|
|
64
|
+
* this implementation; downstream code never has to change.
|
|
65
|
+
*/
|
|
66
|
+
recallCandidates(_taskHint) {
|
|
67
|
+
return this.list();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/shortcuts/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,OAAO,gBAAgB;IACV,OAAO,GAAG,IAAI,GAAG,EAAsC,CAAC;IAEzE;;;;OAIG;IACH,QAAQ,CAAc,QAA+B;QACnD,MAAM,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,4CAA4C,EAAE,wBAAwB,CACvE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,QAAsC,CAAC,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,wDAAwD;IACxD,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;;OAMG;IACH,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,SAAkB;QACjC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortcut router / invoker — the single call site every entry point
|
|
3
|
+
* (extension, ACP plugin, future programmatic API) goes through.
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Lookup** — resolve `id` against the registry; return
|
|
8
|
+
* `invalid_args` when the id is unknown so the LLM gets a
|
|
9
|
+
* structured error instead of a 500.
|
|
10
|
+
* 2. **Platform gate** — check the active device's `info.os` /
|
|
11
|
+
* `info.type` against the shortcut's `descriptor.platforms`.
|
|
12
|
+
* Mismatch → `unsupported_platform`. `"any"` always passes.
|
|
13
|
+
* 3. **Timeout** — wrap the call in a per-shortcut AbortController
|
|
14
|
+
* that honors both `descriptor.timeoutMs` and the host's
|
|
15
|
+
* `AbortSignal`. The two are merged by linking listeners.
|
|
16
|
+
* 4. **Failure shaping** — translate thrown exceptions into
|
|
17
|
+
* `ShortcutFailure { code: "internal_error" }` so the LLM never
|
|
18
|
+
* sees a stack trace. Aborts (host cancel or local timeout) are
|
|
19
|
+
* mapped to `timeout`.
|
|
20
|
+
* 5. **Telemetry** — emit a structured pino log line on every
|
|
21
|
+
* invoke (`event: "shortcut.invoke"`, with id / outcome /
|
|
22
|
+
* durationMs). The label set is the same closed vocabulary as
|
|
23
|
+
* the metric `device_agent_shortcut_invocation_total` (`ok` plus
|
|
24
|
+
* every `ShortcutErrorCode`), so a future Prometheus shim can
|
|
25
|
+
* derive the counter directly from log lines.
|
|
26
|
+
*
|
|
27
|
+
* Why a router and not just direct `shortcut.execute` calls?
|
|
28
|
+
*
|
|
29
|
+
* The plan deliberately separates the registry (catalogue) from the
|
|
30
|
+
* router (call-time concerns). Tests can construct a registry
|
|
31
|
+
* without a router; the router can be swapped (e.g. a future
|
|
32
|
+
* recall-aware variant) without rewriting every call site. The
|
|
33
|
+
* extension only depends on `ShortcutInvoker` — see android-tools.ts.
|
|
34
|
+
*/
|
|
35
|
+
import type { Logger } from "../logger/index.js";
|
|
36
|
+
import type { ShortcutContext, ShortcutResult } from "./types.js";
|
|
37
|
+
import type { ShortcutRegistry } from "./registry.js";
|
|
38
|
+
import type { ShortcutMemoryStore } from "../agent-runtime/shortcuts/index.js";
|
|
39
|
+
export interface ShortcutInvoker {
|
|
40
|
+
invoke<TOut = unknown>(id: string, args: unknown, callerCtx: InvokeCallerContext): Promise<ShortcutResult<TOut>>;
|
|
41
|
+
/** Expose the underlying registry for descriptor generation. */
|
|
42
|
+
readonly registry: ShortcutRegistry;
|
|
43
|
+
}
|
|
44
|
+
export interface ShortcutRouterOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Phase 3 telemetry sink. When provided, every invoke increments the
|
|
47
|
+
* matching counter via `recordSuccess` / `recordFailure`. Failures
|
|
48
|
+
* inside the store are swallowed — telemetry must never break the
|
|
49
|
+
* shortcut path.
|
|
50
|
+
*/
|
|
51
|
+
memoryStore?: ShortcutMemoryStore;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Minimal context the caller is required to supply on every invoke.
|
|
55
|
+
* The router fills in the per-call AbortSignal merge and constructs
|
|
56
|
+
* the final `ShortcutContext` so the shortcut author never has to
|
|
57
|
+
* thread its own controller chain.
|
|
58
|
+
*/
|
|
59
|
+
export interface InvokeCallerContext {
|
|
60
|
+
abortSignal: AbortSignal;
|
|
61
|
+
log: Logger;
|
|
62
|
+
/** Optional MCP runtime forwarded into `ShortcutContext.mcp`. */
|
|
63
|
+
mcp?: ShortcutContext["mcp"];
|
|
64
|
+
/** Optional device facade forwarded into `ShortcutContext.device`. */
|
|
65
|
+
device?: ShortcutContext["device"];
|
|
66
|
+
/** Optional resource facade forwarded into `ShortcutContext.resources`. */
|
|
67
|
+
resources?: ShortcutContext["resources"];
|
|
68
|
+
/**
|
|
69
|
+
* Optional digest of the originating user task — used as the memory
|
|
70
|
+
* store key. Callers SHOULD provide this when memory recording is
|
|
71
|
+
* enabled; absent, the router records under an empty pattern (still
|
|
72
|
+
* usable as a global "shortcut X failure rate" counter, just no
|
|
73
|
+
* task-specific bucketing).
|
|
74
|
+
*/
|
|
75
|
+
taskPattern?: string;
|
|
76
|
+
}
|
|
77
|
+
export declare class ShortcutRouter implements ShortcutInvoker {
|
|
78
|
+
readonly registry: ShortcutRegistry;
|
|
79
|
+
private readonly memoryStore?;
|
|
80
|
+
constructor(registry: ShortcutRegistry, opts?: ShortcutRouterOptions);
|
|
81
|
+
invoke<TOut = unknown>(id: string, args: unknown, caller: InvokeCallerContext): Promise<ShortcutResult<TOut>>;
|
|
82
|
+
/**
|
|
83
|
+
* Phase 3 — fire-and-forget telemetry write. Errors are swallowed by
|
|
84
|
+
* the caller via `.catch(() => undefined)` so a malfunctioning store
|
|
85
|
+
* never blocks the shortcut return path. We still log inside the
|
|
86
|
+
* store on the way down via its own logger when wired by bootstrap.
|
|
87
|
+
*/
|
|
88
|
+
private recordMemory;
|
|
89
|
+
private checkPlatform;
|
|
90
|
+
private logOutcome;
|
|
91
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortcut router / invoker — the single call site every entry point
|
|
3
|
+
* (extension, ACP plugin, future programmatic API) goes through.
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Lookup** — resolve `id` against the registry; return
|
|
8
|
+
* `invalid_args` when the id is unknown so the LLM gets a
|
|
9
|
+
* structured error instead of a 500.
|
|
10
|
+
* 2. **Platform gate** — check the active device's `info.os` /
|
|
11
|
+
* `info.type` against the shortcut's `descriptor.platforms`.
|
|
12
|
+
* Mismatch → `unsupported_platform`. `"any"` always passes.
|
|
13
|
+
* 3. **Timeout** — wrap the call in a per-shortcut AbortController
|
|
14
|
+
* that honors both `descriptor.timeoutMs` and the host's
|
|
15
|
+
* `AbortSignal`. The two are merged by linking listeners.
|
|
16
|
+
* 4. **Failure shaping** — translate thrown exceptions into
|
|
17
|
+
* `ShortcutFailure { code: "internal_error" }` so the LLM never
|
|
18
|
+
* sees a stack trace. Aborts (host cancel or local timeout) are
|
|
19
|
+
* mapped to `timeout`.
|
|
20
|
+
* 5. **Telemetry** — emit a structured pino log line on every
|
|
21
|
+
* invoke (`event: "shortcut.invoke"`, with id / outcome /
|
|
22
|
+
* durationMs). The label set is the same closed vocabulary as
|
|
23
|
+
* the metric `device_agent_shortcut_invocation_total` (`ok` plus
|
|
24
|
+
* every `ShortcutErrorCode`), so a future Prometheus shim can
|
|
25
|
+
* derive the counter directly from log lines.
|
|
26
|
+
*
|
|
27
|
+
* Why a router and not just direct `shortcut.execute` calls?
|
|
28
|
+
*
|
|
29
|
+
* The plan deliberately separates the registry (catalogue) from the
|
|
30
|
+
* router (call-time concerns). Tests can construct a registry
|
|
31
|
+
* without a router; the router can be swapped (e.g. a future
|
|
32
|
+
* recall-aware variant) without rewriting every call site. The
|
|
33
|
+
* extension only depends on `ShortcutInvoker` — see android-tools.ts.
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
36
|
+
export class ShortcutRouter {
|
|
37
|
+
registry;
|
|
38
|
+
memoryStore;
|
|
39
|
+
constructor(registry, opts = {}) {
|
|
40
|
+
this.registry = registry;
|
|
41
|
+
if (opts.memoryStore !== undefined) {
|
|
42
|
+
this.memoryStore = opts.memoryStore;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async invoke(id, args, caller) {
|
|
46
|
+
const startedAt = Date.now();
|
|
47
|
+
const sc = this.registry.get(id);
|
|
48
|
+
if (!sc) {
|
|
49
|
+
const fail = makeFailure("invalid_args", `unknown shortcut id: ${id}`);
|
|
50
|
+
this.logOutcome(caller.log, id, fail, Date.now() - startedAt);
|
|
51
|
+
return fail;
|
|
52
|
+
}
|
|
53
|
+
const platformErr = await this.checkPlatform(sc, caller);
|
|
54
|
+
if (platformErr) {
|
|
55
|
+
this.logOutcome(caller.log, id, platformErr, Date.now() - startedAt);
|
|
56
|
+
return platformErr;
|
|
57
|
+
}
|
|
58
|
+
const timeoutMs = sc.descriptor.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
59
|
+
const localCtl = new AbortController();
|
|
60
|
+
const onHostAbort = () => localCtl.abort();
|
|
61
|
+
if (caller.abortSignal.aborted)
|
|
62
|
+
localCtl.abort();
|
|
63
|
+
else
|
|
64
|
+
caller.abortSignal.addEventListener("abort", onHostAbort, { once: true });
|
|
65
|
+
const timer = setTimeout(() => localCtl.abort(), timeoutMs);
|
|
66
|
+
const ctx = {
|
|
67
|
+
...(caller.mcp !== undefined ? { mcp: caller.mcp } : {}),
|
|
68
|
+
...(caller.device !== undefined ? { device: caller.device } : {}),
|
|
69
|
+
...(caller.resources !== undefined ? { resources: caller.resources } : {}),
|
|
70
|
+
abortSignal: localCtl.signal,
|
|
71
|
+
log: caller.log,
|
|
72
|
+
};
|
|
73
|
+
let outcome;
|
|
74
|
+
try {
|
|
75
|
+
const out = await sc.execute(args, ctx);
|
|
76
|
+
outcome = out;
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
// Aborts (host cancel + local timeout) collapse to "timeout";
|
|
80
|
+
// anything else is an unhandled bug and surfaces as
|
|
81
|
+
// internal_error so the LLM still gets a structured failure.
|
|
82
|
+
if (localCtl.signal.aborted) {
|
|
83
|
+
outcome = makeFailure("timeout", `shortcut timed out after ${timeoutMs}ms`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
87
|
+
outcome = makeFailure("internal_error", message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
caller.abortSignal.removeEventListener("abort", onHostAbort);
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
}
|
|
94
|
+
const durationMs = Date.now() - startedAt;
|
|
95
|
+
const stamped = withDuration(outcome, durationMs);
|
|
96
|
+
this.logOutcome(caller.log, id, stamped, durationMs);
|
|
97
|
+
this.recordMemory(id, stamped, caller).catch(() => undefined);
|
|
98
|
+
return stamped;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Phase 3 — fire-and-forget telemetry write. Errors are swallowed by
|
|
102
|
+
* the caller via `.catch(() => undefined)` so a malfunctioning store
|
|
103
|
+
* never blocks the shortcut return path. We still log inside the
|
|
104
|
+
* store on the way down via its own logger when wired by bootstrap.
|
|
105
|
+
*/
|
|
106
|
+
async recordMemory(id, res, caller) {
|
|
107
|
+
if (!this.memoryStore)
|
|
108
|
+
return;
|
|
109
|
+
const pattern = caller.taskPattern ?? "";
|
|
110
|
+
if (res.ok) {
|
|
111
|
+
await this.memoryStore.recordSuccess(pattern, id);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
await this.memoryStore.recordFailure(pattern, id, res.code);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async checkPlatform(sc, caller) {
|
|
118
|
+
const platforms = sc.descriptor.platforms;
|
|
119
|
+
if (platforms.includes("any"))
|
|
120
|
+
return null;
|
|
121
|
+
if (!caller.device) {
|
|
122
|
+
// No device facade — we can't check, so fail closed.
|
|
123
|
+
return makeFailure("unsupported_platform", `shortcut "${sc.descriptor.id}" requires a device but none is attached`);
|
|
124
|
+
}
|
|
125
|
+
let info;
|
|
126
|
+
try {
|
|
127
|
+
info = await caller.device.getInfo();
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
return makeFailure("unsupported_platform", `shortcut "${sc.descriptor.id}" platform check failed: ${e.message}`);
|
|
131
|
+
}
|
|
132
|
+
const tag = (info.type ?? info.os ?? "").toLowerCase();
|
|
133
|
+
const matches = platforms.some((p) => p === "any" || tag.includes(p));
|
|
134
|
+
if (matches)
|
|
135
|
+
return null;
|
|
136
|
+
return makeFailure("unsupported_platform", `shortcut "${sc.descriptor.id}" not supported on platform "${tag}"`);
|
|
137
|
+
}
|
|
138
|
+
logOutcome(log, id, res, durationMs) {
|
|
139
|
+
log.info({
|
|
140
|
+
event: "shortcut.invoke",
|
|
141
|
+
shortcut_id: id,
|
|
142
|
+
result: res.ok ? "ok" : res.code,
|
|
143
|
+
durationMs,
|
|
144
|
+
}, "shortcut.invoke");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/* -------------------------------------------------------------------- */
|
|
148
|
+
/* Helpers */
|
|
149
|
+
/* -------------------------------------------------------------------- */
|
|
150
|
+
function makeFailure(code, message) {
|
|
151
|
+
return { ok: false, code, message };
|
|
152
|
+
}
|
|
153
|
+
function withDuration(res, durationMs) {
|
|
154
|
+
if (res.ok)
|
|
155
|
+
return { ...res, durationMs };
|
|
156
|
+
return { ...res, durationMs };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/shortcuts/router.ts"],"names":[],"mappings":"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"}
|