@mono-agent/agent-app 0.11.5 → 0.13.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/README.md +54 -17
- package/dist/adapter-send-tools.d.ts.map +1 -1
- package/dist/adapter-send-tools.js +126 -34
- package/dist/adapter-send-tools.js.map +1 -1
- package/dist/app-controller-lifecycle.d.ts.map +1 -1
- package/dist/app-controller-lifecycle.js +2 -6
- package/dist/app-controller-lifecycle.js.map +1 -1
- package/dist/app-controller-maintenance.d.ts.map +1 -1
- package/dist/app-controller-maintenance.js +2 -1
- package/dist/app-controller-maintenance.js.map +1 -1
- package/dist/app-controller-memory-health.d.ts +1 -1
- package/dist/app-controller-memory-health.d.ts.map +1 -1
- package/dist/app-controller-memory-health.js +5 -1
- package/dist/app-controller-memory-health.js.map +1 -1
- package/dist/app-controller-responder.d.ts.map +1 -1
- package/dist/app-controller-responder.js +8 -3
- package/dist/app-controller-responder.js.map +1 -1
- package/dist/app-controller-traceability.d.ts.map +1 -1
- package/dist/app-controller-traceability.js +15 -1
- package/dist/app-controller-traceability.js.map +1 -1
- package/dist/app-controller.d.ts +14 -1
- package/dist/app-controller.d.ts.map +1 -1
- package/dist/app-controller.js +61 -9
- package/dist/app-controller.js.map +1 -1
- package/dist/audit-runs.d.ts.map +1 -1
- package/dist/audit-runs.js +12 -2
- package/dist/audit-runs.js.map +1 -1
- package/dist/background-runtime.d.ts +26 -0
- package/dist/background-runtime.d.ts.map +1 -1
- package/dist/background-runtime.js +874 -46
- package/dist/background-runtime.js.map +1 -1
- package/dist/background.d.ts +12 -2
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +195 -40
- package/dist/background.js.map +1 -1
- package/dist/channel-drivers/live.d.ts +3 -2
- package/dist/channel-drivers/live.d.ts.map +1 -1
- package/dist/channel-drivers/live.js +3 -2
- package/dist/channel-drivers/live.js.map +1 -1
- package/dist/channel-drivers/slack.d.ts.map +1 -1
- package/dist/channel-drivers/slack.js +6 -0
- package/dist/channel-drivers/slack.js.map +1 -1
- package/dist/channel-drivers/telegram.d.ts.map +1 -1
- package/dist/channel-drivers/telegram.js +20 -4
- package/dist/channel-drivers/telegram.js.map +1 -1
- package/dist/channel-drivers/tui.d.ts.map +1 -1
- package/dist/channel-drivers/tui.js +24 -0
- package/dist/channel-drivers/tui.js.map +1 -1
- package/dist/channel-runtime-controls.d.ts +23 -0
- package/dist/channel-runtime-controls.d.ts.map +1 -0
- package/dist/channel-runtime-controls.js +63 -0
- package/dist/channel-runtime-controls.js.map +1 -0
- package/dist/channel-status-display.d.ts +15 -0
- package/dist/channel-status-display.d.ts.map +1 -0
- package/dist/channel-status-display.js +48 -0
- package/dist/channel-status-display.js.map +1 -0
- package/dist/cli-args.d.ts +19 -22
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +115 -68
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-background-command.d.ts +1 -0
- package/dist/cli-background-command.d.ts.map +1 -1
- package/dist/cli-background-command.js +72 -16
- package/dist/cli-background-command.js.map +1 -1
- package/dist/cli-commands.d.ts +4 -2
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +51 -47
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli-help.d.ts +19 -1
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +217 -70
- package/dist/cli-help.js.map +1 -1
- package/dist/cli-init-command.d.ts.map +1 -1
- package/dist/cli-init-command.js +4 -18
- package/dist/cli-init-command.js.map +1 -1
- package/dist/cli-install-skill-command.d.ts.map +1 -1
- package/dist/cli-install-skill-command.js +32 -3
- package/dist/cli-install-skill-command.js.map +1 -1
- package/dist/cli-runs-command.d.ts +13 -0
- package/dist/cli-runs-command.d.ts.map +1 -0
- package/dist/cli-runs-command.js +70 -0
- package/dist/cli-runs-command.js.map +1 -0
- package/dist/cli-sandbox-command.d.ts +1 -1
- package/dist/cli-sandbox-command.d.ts.map +1 -1
- package/dist/cli-sandbox-command.js +14 -2
- package/dist/cli-sandbox-command.js.map +1 -1
- package/dist/cli-validate-config-command.d.ts +24 -5
- package/dist/cli-validate-config-command.d.ts.map +1 -1
- package/dist/cli-validate-config-command.js +120 -41
- package/dist/cli-validate-config-command.js.map +1 -1
- package/dist/config-reference.d.ts +1 -1
- package/dist/config-reference.d.ts.map +1 -1
- package/dist/config-reference.js +63 -1
- package/dist/config-reference.js.map +1 -1
- package/dist/configured-agent.js +3 -1
- package/dist/configured-agent.js.map +1 -1
- package/dist/docs-mcp-pairing.d.ts +35 -0
- package/dist/docs-mcp-pairing.d.ts.map +1 -0
- package/dist/docs-mcp-pairing.js +311 -0
- package/dist/docs-mcp-pairing.js.map +1 -0
- package/dist/doctor.d.ts +6 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +6 -5
- package/dist/doctor.js.map +1 -1
- package/dist/install-skill.d.ts +2 -0
- package/dist/install-skill.d.ts.map +1 -1
- package/dist/install-skill.js +10 -4
- package/dist/install-skill.js.map +1 -1
- package/dist/interaction-bridge.d.ts +2 -0
- package/dist/interaction-bridge.d.ts.map +1 -1
- package/dist/interaction-bridge.js +46 -1
- package/dist/interaction-bridge.js.map +1 -1
- package/dist/launchd.d.ts +18 -0
- package/dist/launchd.d.ts.map +1 -1
- package/dist/launchd.js +69 -0
- package/dist/launchd.js.map +1 -1
- package/dist/local-configuration.d.ts +2 -2
- package/dist/local-configuration.d.ts.map +1 -1
- package/dist/local-configuration.js +10 -10
- package/dist/local-configuration.js.map +1 -1
- package/dist/managed-runtime-publication.d.ts +22 -0
- package/dist/managed-runtime-publication.d.ts.map +1 -0
- package/dist/managed-runtime-publication.js +91 -0
- package/dist/managed-runtime-publication.js.map +1 -0
- package/dist/managed-startup.d.ts +8 -0
- package/dist/managed-startup.d.ts.map +1 -0
- package/dist/managed-startup.js +12 -0
- package/dist/managed-startup.js.map +1 -0
- package/dist/memory-retrieval.d.ts.map +1 -1
- package/dist/memory-retrieval.js +31 -18
- package/dist/memory-retrieval.js.map +1 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +12 -2
- package/dist/metrics.js.map +1 -1
- package/dist/modules/known-tools.d.ts +2 -2
- package/dist/modules/known-tools.d.ts.map +1 -1
- package/dist/modules/known-tools.js +2 -1
- package/dist/modules/known-tools.js.map +1 -1
- package/dist/notify-runtime.d.ts +26 -0
- package/dist/notify-runtime.d.ts.map +1 -0
- package/dist/notify-runtime.js +27 -0
- package/dist/notify-runtime.js.map +1 -0
- package/dist/notify-tool.d.ts +51 -0
- package/dist/notify-tool.d.ts.map +1 -0
- package/dist/notify-tool.js +182 -0
- package/dist/notify-tool.js.map +1 -0
- package/dist/posted-reply-history.d.ts.map +1 -1
- package/dist/posted-reply-history.js +7 -0
- package/dist/posted-reply-history.js.map +1 -1
- package/dist/project-skills.d.ts +1 -1
- package/dist/project-skills.d.ts.map +1 -1
- package/dist/project-skills.js +9 -7
- package/dist/project-skills.js.map +1 -1
- package/dist/recipes/base.d.ts +15 -0
- package/dist/recipes/base.d.ts.map +1 -0
- package/dist/recipes/base.js +51 -0
- package/dist/recipes/base.js.map +1 -0
- package/dist/recipes/catalog.d.ts +4 -0
- package/dist/recipes/catalog.d.ts.map +1 -0
- package/dist/recipes/catalog.js +525 -0
- package/dist/recipes/catalog.js.map +1 -0
- package/dist/recipes/index.d.ts +11 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +14 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/types.d.ts +70 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +15 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/request-model-override.d.ts +3 -2
- package/dist/request-model-override.d.ts.map +1 -1
- package/dist/request-model-override.js +13 -7
- package/dist/request-model-override.js.map +1 -1
- package/dist/run-history.d.ts.map +1 -1
- package/dist/run-history.js +35 -22
- package/dist/run-history.js.map +1 -1
- package/dist/runtime-provenance.d.ts.map +1 -1
- package/dist/runtime-provenance.js +10 -5
- package/dist/runtime-provenance.js.map +1 -1
- package/dist/sessions-command.d.ts +53 -0
- package/dist/sessions-command.d.ts.map +1 -0
- package/dist/sessions-command.js +309 -0
- package/dist/sessions-command.js.map +1 -0
- package/dist/setup.d.ts +29 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +97 -0
- package/dist/setup.js.map +1 -0
- package/dist/tui-command.d.ts +1 -1
- package/dist/tui-command.d.ts.map +1 -1
- package/dist/tui-command.js +6 -5
- package/dist/tui-command.js.map +1 -1
- package/dist/web-command.d.ts +109 -43
- package/dist/web-command.d.ts.map +1 -1
- package/dist/web-command.js +1108 -237
- package/dist/web-command.js.map +1 -1
- package/dist/wizard/from-flags.d.ts +0 -1
- package/dist/wizard/from-flags.d.ts.map +1 -1
- package/dist/wizard/from-flags.js +1 -8
- package/dist/wizard/from-flags.js.map +1 -1
- package/dist/wizard/index.d.ts +1 -1
- package/dist/wizard/index.d.ts.map +1 -1
- package/dist/wizard/index.js +1 -1
- package/dist/wizard/index.js.map +1 -1
- package/dist/wizard/presets.d.ts +3 -12
- package/dist/wizard/presets.d.ts.map +1 -1
- package/dist/wizard/presets.js +3 -15
- package/dist/wizard/presets.js.map +1 -1
- package/dist/wizard/prompts.d.ts.map +1 -1
- package/dist/wizard/prompts.js +2 -1
- package/dist/wizard/prompts.js.map +1 -1
- package/dist/wizard/run.d.ts.map +1 -1
- package/dist/wizard/run.js +9 -9
- package/dist/wizard/run.js.map +1 -1
- package/package.json +15 -15
- package/schema/mono-agent.config.schema.json +70 -2
- package/skills/mono-agent-composer/SKILL.md +14 -6
- package/skills/mono-agent-composer/agents/openai.yaml +1 -1
- package/skills/mono-agent-composer/references/config-blueprint.md +30 -9
- package/skills/mono-agent-composer/references/discovery-questions.md +10 -5
- package/skills/mono-agent-composer/references/feature-coverage.md +14 -12
- package/skills/mono-agent-composer/references/package-map.md +10 -3
- package/skills/mono-agent-composer/references/playbooks.md +8 -8
- package/skills/mono-agent-composer/references/validation.md +4 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Config-first mono-agent host. Reads one `mono-agent.config.json` in a folder,
|
|
4
4
|
builds the configured responder, and starts every configured communication
|
|
5
5
|
channel plus traceability. Ships the
|
|
6
|
-
`mono-agent` CLI (`init`, `auth`, `sandbox`, `validate`, `memory`, `tui`, `start`) so an agent folder works without
|
|
6
|
+
`mono-agent` CLI (`init`, `auth`, `sandbox`, `validate`, `memory`, `tui`, `web`, `start`) so an agent folder works without
|
|
7
7
|
hand-written composition code.
|
|
8
8
|
|
|
9
9
|
Setup has two deliberate wall-clock paths: flags or non-TTY input use the fast scaffold-only path (unless explicit `--auth` adds provider setup) and never claim readiness. Bare `mono-agent init` on a TTY makes one real no-tool model call per selected route before committing the scaffold, with timeouts of 90s for each cloud route and 240s for each local route.
|
|
@@ -42,6 +42,10 @@ Turn a folder's `mono-agent.config.json` into a running agent host:
|
|
|
42
42
|
provider-free strict health and payload-free intake inspect/retry/resolve).
|
|
43
43
|
- Scaffold (`mono-agent init`) and validate (`mono-agent validate`) agent
|
|
44
44
|
folders non-destructively.
|
|
45
|
+
- Operate the machine-wide `@mono-agent/web` assistant-ui console through
|
|
46
|
+
`mono-agent web`. The `@mono-agent/session-web` recorder still ships but its
|
|
47
|
+
`mono-agent sessions` launcher was removed; use `mono-agent tui`
|
|
48
|
+
(recorded-run replay) or `mono-agent web` (live console).
|
|
45
49
|
|
|
46
50
|
## Install / Usage
|
|
47
51
|
|
|
@@ -116,7 +120,7 @@ action fails the check.
|
|
|
116
120
|
Escape or Ctrl-C interrupts preflight; recovery can resume verified routes when
|
|
117
121
|
the non-secret plan fingerprint still matches, restart all checks, edit choices,
|
|
118
122
|
or cancel. Authentication repair clears every prior route proof because it can
|
|
119
|
-
replace credential bytes. Guided commit atomically creates the config and rechecks its exact snapshot after validation. On macOS it then creates or refreshes the canonical per-config launchd service
|
|
123
|
+
replace credential bytes. Guided commit atomically creates the config and rechecks its exact snapshot after validation. On macOS it then creates or refreshes the canonical per-config launchd service and waits up to 60 seconds for a fresh trace whose durable `metadata.lifecycle.startupCompleted` proof is true. The worker publishes that proof only after channels, memory rituals, and final memory-health work complete; later trace refreshes change the diagnostic `metadata.reason` without revoking readiness. The controller also re-proves the live launchd PID, exact snapshot, current channel/memory health, and reachable TUI before it opens `mono-agent tui --configure` against that background responder. A readiness timeout or trace/TUI-probe error preserves the committed files and skips chat, then unloads the worker plus scheduled maintenance and removes their definitions only when stopped state is proven. If cleanup cannot be proven, the command says that a process may still be running and prints exact `start`, `status`, and `logs --follow` recovery commands plus log paths. Workers from an older release that have no durable lifecycle marker must restart once before configuration can attach. Off macOS, conversational configuration is unavailable: the wizard preserves the files and gives manual edit/validate, foreground-start, and ordinary-TUI guidance without claiming readiness. Any flag or non-TTY invocation remains scaffold-only and never starts a process.
|
|
120
124
|
|
|
121
125
|
Every scaffold selects versioned `mono-agent-configure` and `mono-agent-memory`
|
|
122
126
|
skills from `./skills` with index disclosure. `ReadSkill` remains separate from
|
|
@@ -126,14 +130,28 @@ canonical owner-only non-symlink parent chain, per-project owner lock, and
|
|
|
126
130
|
compare-and-swap activation prevent outside or concurrent
|
|
127
131
|
operator edits from being overwritten, and a partial activation restores only
|
|
128
132
|
files that still equal the managed bytes it wrote.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
`
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
The persistent SELF-CONFIG workflow guidance is managed-skill version `1.2.0`.
|
|
134
|
+
Existing unchanged copies are reported as stale and are never rewritten on TUI
|
|
135
|
+
startup; run `mono-agent install-skill --project --update` explicitly to refresh them.
|
|
136
|
+
|
|
137
|
+
Harness-mode `mono-agent install-skill` also pairs the exact matching
|
|
138
|
+
`@mono-agent/docs-mcp` version with available selected Codex and Claude Code
|
|
139
|
+
CLIs. That read-only companion gives `mono-agent-composer` offline semantic and
|
|
140
|
+
exact-identifier search over the public docs and its authoritative references.
|
|
141
|
+
Use `--no-docs-mcp` for a skill-only install. Managed MCP and skill changes are
|
|
142
|
+
transactional; an unrelated entry named `mono-agent-docs` is never overwritten,
|
|
143
|
+
including with `--force`. Project `--check` / `--update` mode does not touch
|
|
144
|
+
harness MCP configuration.
|
|
145
|
+
|
|
146
|
+
In the separate, visibly marked **SELF-CONFIG** session only, the background app injects proposal-only
|
|
147
|
+
`ProposeAgentConfiguration`. The opening message shows a user-led map of identity/knowledge,
|
|
148
|
+
runtime/models, skills/tools/MCP/plugins, memory, channels/APIs/A2A, automation,
|
|
149
|
+
security, observability/operations, and acceptance criteria, then builds the chosen
|
|
150
|
+
workflow conversationally. It says never to enter secrets and to expect a separate
|
|
151
|
+
host approval before anything changes. Approval, rejection, a proposal-free turn,
|
|
152
|
+
`done`, and `no changes` all keep SELF-CONFIG active; only `/quit`, `/exit`, or
|
|
153
|
+
double `ctrl+c` exits the session, and quitting leaves the background agent running.
|
|
154
|
+
The host accepts only a fail-closed low-risk
|
|
137
155
|
allowlist: public name; effort, turn/session UX; selected project skills and
|
|
138
156
|
disclosure; memory size or MemoryRecall enablement; semantic tool-policy
|
|
139
157
|
tightening; and the separately validated Role body. Every path, memory-tier or
|
|
@@ -150,12 +168,15 @@ tool only. Pure direct-Codex chains use its native read-only plan posture;
|
|
|
150
168
|
mixed chains keep the finite proposal surface so a route that cannot represent
|
|
151
169
|
it cannot widen authority. Direct OpenCode cannot receive the host-owned MCP
|
|
152
170
|
proposal capability: a direct-OpenCode primary is routed through a configured
|
|
153
|
-
proposal-capable fallback, while a direct-OpenCode fallback makes
|
|
154
|
-
|
|
171
|
+
proposal-capable fallback, while a direct-OpenCode fallback makes self-configuration
|
|
172
|
+
unavailable with explicit remediation. The approval card shows
|
|
155
173
|
every full, untruncated JSON patch value and pages through the exact Role body
|
|
156
174
|
while keeping Reject/Approve reachable, and rejects
|
|
157
|
-
terminal-control or bidi-control review text before displaying it.
|
|
158
|
-
|
|
175
|
+
terminal-control or bidi-control review text before displaying it. The configuration
|
|
176
|
+
conversation id stays stable across incremental checkpoints and verified restarts;
|
|
177
|
+
each settled turn receives a fresh opaque proposal capability plus a safe host-outcome
|
|
178
|
+
summary. Fast follow-up text remains in the editor until settlement and is never sent
|
|
179
|
+
as ordinary chat or to a stale endpoint. Remote/proactive channels never receive this tool.
|
|
159
180
|
|
|
160
181
|
Before the first macOS background launch, the CLI copies the exact package and
|
|
161
182
|
already-resolved dependency closure it is currently executing—including configured
|
|
@@ -168,7 +189,16 @@ digest are bound into the runtime marker and verified on every reuse. The Launch
|
|
|
168
189
|
`npm create`/npx cache. Existing verified runtime snapshots are reused and
|
|
169
190
|
retained because another agent may still reference them. A loaded job is fully
|
|
170
191
|
booted out and bootstrapped again so rewritten arguments and environment are
|
|
171
|
-
adopted.
|
|
192
|
+
adopted. During a slow install, the existing healthy worker remains loaded. An
|
|
193
|
+
owner-private per-instance publication barrier makes any KeepAlive respawn wait
|
|
194
|
+
until the replacement closure and plist are committed; dead or PID-reused
|
|
195
|
+
controller ownership is recovered by process incarnation. The replacement
|
|
196
|
+
plist carries a path-free proof of the finalized marker, and the worker
|
|
197
|
+
revalidates its exact canonical CLI, marker, manifest fingerprint, and launch
|
|
198
|
+
boundary before loading config or channels. Only that verified active closure
|
|
199
|
+
is automatically reopened read-only by app-owned SRT; the runtimes parent and
|
|
200
|
+
historical sibling closures remain outside the implicit policy. Launchd enters
|
|
201
|
+
Node through `/usr/bin/env -i`, so inherited variables
|
|
172
202
|
such as `NODE_OPTIONS` cannot execute before the worker's allowlisted environment
|
|
173
203
|
is established. Every foreground worker holds one owner-only lifetime lease for its
|
|
174
204
|
canonical config, so a managed and manual host cannot run together. A per-config
|
|
@@ -270,6 +300,12 @@ bounded by newest whole interactions, without changing the outward message or
|
|
|
270
300
|
long-term memory capture. `TelegramAskButtons` with `wait: false` continues to produce a
|
|
271
301
|
synthetic next turn when the user taps later.
|
|
272
302
|
|
|
303
|
+
For blocking `TelegramAskButtons`, the next plain-text Telegram message is also
|
|
304
|
+
a valid custom answer. It resolves the same in-flight tool call and the app asks
|
|
305
|
+
the Telegram sink to remove the inline keyboard. The built-in Telegram `/new`
|
|
306
|
+
command uses the configured responder's host-owned reset surface to clear only
|
|
307
|
+
that conversation and force skill/startup-context reload on its next turn.
|
|
308
|
+
|
|
273
309
|
The app publishes a cached, content-free `memoryHealth` snapshot in the primary
|
|
274
310
|
trace-source heartbeat and any enabled best-effort global mirror. Built-in
|
|
275
311
|
health is computed through a dynamic memory import so a native SQLite ABI
|
|
@@ -318,8 +354,9 @@ a declared but missing variable stays `waiting` and never retries keyless.
|
|
|
318
354
|
Changing provider, model, or dimension on an existing root requires a stopped,
|
|
319
355
|
config-aware `mono-agent memory rebuild --json`. BuJo uses the selected
|
|
320
356
|
embeddings service independently from its explicit capture LLM (`agent-host` in
|
|
321
|
-
generated configs, or an authored Ollama block). The
|
|
322
|
-
|
|
357
|
+
generated configs, or an authored Ollama block). The standalone `memory-bujo`
|
|
358
|
+
maintenance CLI has been removed; run every memory operation config-aware through
|
|
359
|
+
`mono-agent memory <subcommand>` from the agent folder.
|
|
323
360
|
`retry` makes dead/delayed intake due for the
|
|
324
361
|
next store start; `resolve` explicitly abandons one item without claiming
|
|
325
362
|
capture succeeded, keeps permanent duplicate protection, and refuses a retained
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-send-tools.d.ts","sourceRoot":"","sources":["../src/adapter-send-tools.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAEV,WAAW,EACZ,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAGV,qBAAqB,EAGtB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter-send-tools.d.ts","sourceRoot":"","sources":["../src/adapter-send-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -351,9 +351,7 @@ async function awaitBridgeAsk(settings, askId, toolName, extra, fetchImpl, signa
|
|
|
351
351
|
await sendAskProgress(extra, Math.round((Date.now() - startedMs) / 1000));
|
|
352
352
|
const status = poll.body.status;
|
|
353
353
|
if (status === "answered" && typeof poll.body.answer === "string") {
|
|
354
|
-
const answeredText =
|
|
355
|
-
? `The user tapped:\n${poll.body.answer}`
|
|
356
|
-
: `The user answered:\n${poll.body.answer}`;
|
|
354
|
+
const answeredText = `The user answered:\n${poll.body.answer}`;
|
|
357
355
|
return askToolResult(answeredText, { answered: true, answer: poll.body.answer }, extraStructured);
|
|
358
356
|
}
|
|
359
357
|
if (status === "expired") {
|
|
@@ -578,7 +576,7 @@ function registerTelegramSendTool(server, settings, client, deliveryHistory, fet
|
|
|
578
576
|
disable_web_page_preview: z.boolean().optional().describe("Disable Telegram link previews."),
|
|
579
577
|
},
|
|
580
578
|
}, async (args, extra) => {
|
|
581
|
-
assertTelegramChatAllowed(settings, args.chat_id);
|
|
579
|
+
assertTelegramChatAllowed(settings, args.chat_id, "TelegramSendMessage");
|
|
582
580
|
const result = await client.sendMessage({
|
|
583
581
|
chat_id: args.chat_id,
|
|
584
582
|
text: args.text,
|
|
@@ -677,10 +675,42 @@ async function editExpiredTelegramAskMessage(client, adapter, params) {
|
|
|
677
675
|
// Best-effort: a failed expiry edit must never replace the ask result.
|
|
678
676
|
}
|
|
679
677
|
}
|
|
678
|
+
/**
|
|
679
|
+
* Best-effort: remove a keyboard that was sent but could not be registered with
|
|
680
|
+
* the interaction bridge. Re-editing without reply_markup clears the buttons;
|
|
681
|
+
* use an independent bounded signal and preserve the primary bridge failure.
|
|
682
|
+
*/
|
|
683
|
+
async function dismissUnregisteredTelegramAskKeyboard(client, adapter, params) {
|
|
684
|
+
try {
|
|
685
|
+
const rendered = adapter.renderTelegramMarkdown(params.rawSource);
|
|
686
|
+
const signal = AbortSignal.timeout(TELEGRAM_ASK_EXPIRY_EDIT_TIMEOUT_MS);
|
|
687
|
+
try {
|
|
688
|
+
await client.editMessageText({
|
|
689
|
+
chat_id: params.chat_id,
|
|
690
|
+
message_id: params.message_id,
|
|
691
|
+
text: rendered,
|
|
692
|
+
parse_mode: "MarkdownV2",
|
|
693
|
+
}, { signal });
|
|
694
|
+
}
|
|
695
|
+
catch (error) {
|
|
696
|
+
if (!isTelegramParseError(error, adapter)) {
|
|
697
|
+
throw error;
|
|
698
|
+
}
|
|
699
|
+
await client.editMessageText({
|
|
700
|
+
chat_id: params.chat_id,
|
|
701
|
+
message_id: params.message_id,
|
|
702
|
+
text: params.rawSource,
|
|
703
|
+
}, { signal });
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
catch {
|
|
707
|
+
// Best-effort: keyboard cleanup must not replace the bridge failure.
|
|
708
|
+
}
|
|
709
|
+
}
|
|
680
710
|
function registerTelegramAskTool(server, settings, client, adapter, fetchImpl) {
|
|
681
711
|
server.registerTool("TelegramAskButtons", {
|
|
682
712
|
title: "Ask via Telegram buttons",
|
|
683
|
-
description: "Ask the owner a question in an allowed Telegram chat with tappable inline-keyboard buttons (e.g. a confirmation or a multiple-choice). By default WAITS for
|
|
713
|
+
description: "Ask the owner a question in an allowed Telegram chat with tappable inline-keyboard buttons (e.g. a confirmation or a multiple-choice). By default WAITS for either a button tap or the owner's next plain-text custom reply (up to the ask timeout) and returns that answer; a second concurrent ask in the same chat fails. On a proactive or scheduled turn (cron/heartbeat) set `wait:false`: the buttons are sent and the tool returns immediately, and the tap arrives later as a new message quoting the question.",
|
|
684
714
|
inputSchema: {
|
|
685
715
|
chat_id: z.union([z.string().min(1), z.number().int()]).describe("Telegram chat id from the adapter allowlist."),
|
|
686
716
|
question: z.string().min(1).describe("The question to show above the buttons."),
|
|
@@ -688,15 +718,15 @@ function registerTelegramAskTool(server, settings, client, adapter, fetchImpl) {
|
|
|
688
718
|
.array(z.string().min(1).max(100))
|
|
689
719
|
.min(2)
|
|
690
720
|
.max(adapter.TELEGRAM_ASK_MAX_OPTIONS)
|
|
691
|
-
.describe("Button labels (2–8).
|
|
721
|
+
.describe("Button labels (2–8). A tap returns its label; while waiting, plain text is accepted as a custom answer."),
|
|
692
722
|
note: z.string().min(1).optional().describe("Optional extra context shown beneath the question."),
|
|
693
723
|
wait: z
|
|
694
724
|
.boolean()
|
|
695
725
|
.optional()
|
|
696
|
-
.describe("Default true: block
|
|
726
|
+
.describe("Default true: block for a button tap or custom text reply (up to the ask timeout). Set false on proactive/scheduled (cron/heartbeat) turns — send the buttons and return immediately; a tapped answer arrives later as a new message quoting the question."),
|
|
697
727
|
},
|
|
698
728
|
}, async (args, extra) => {
|
|
699
|
-
assertTelegramChatAllowed(settings, args.chat_id);
|
|
729
|
+
assertTelegramChatAllowed(settings, args.chat_id, "TelegramAskButtons");
|
|
700
730
|
const inlineKeyboard = args.options.map((label, index) => [
|
|
701
731
|
{ text: label, callback_data: adapter.telegramAskCallbackData(index) },
|
|
702
732
|
]);
|
|
@@ -761,6 +791,33 @@ function registerTelegramAskTool(server, settings, client, adapter, fetchImpl) {
|
|
|
761
791
|
await cleanupBridgeAskBestEffort(bridge, fetchImpl, askId);
|
|
762
792
|
throw error;
|
|
763
793
|
}
|
|
794
|
+
const presentation = await (async () => {
|
|
795
|
+
try {
|
|
796
|
+
return await askBridgeRequest(bridge, fetchImpl, "PUT", `/v1/asks/${encodeURIComponent(askId)}/presentation`, { messageRef: String(result.message_id) }, extra.signal);
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
await Promise.all([
|
|
800
|
+
cleanupBridgeAskBestEffort(bridge, fetchImpl, askId),
|
|
801
|
+
dismissUnregisteredTelegramAskKeyboard(client, adapter, {
|
|
802
|
+
chat_id: result.chat.id,
|
|
803
|
+
message_id: result.message_id,
|
|
804
|
+
rawSource: source,
|
|
805
|
+
}),
|
|
806
|
+
]);
|
|
807
|
+
throw error;
|
|
808
|
+
}
|
|
809
|
+
})();
|
|
810
|
+
if (presentation.status !== 204) {
|
|
811
|
+
await Promise.all([
|
|
812
|
+
cleanupBridgeAskBestEffort(bridge, fetchImpl, askId),
|
|
813
|
+
dismissUnregisteredTelegramAskKeyboard(client, adapter, {
|
|
814
|
+
chat_id: result.chat.id,
|
|
815
|
+
message_id: result.message_id,
|
|
816
|
+
rawSource: source,
|
|
817
|
+
}),
|
|
818
|
+
]);
|
|
819
|
+
throw new Error(`TelegramAskButtons: the interaction bridge rejected the keyboard reference (HTTP ${String(presentation.status)}).`);
|
|
820
|
+
}
|
|
764
821
|
const askResult = await awaitBridgeAsk(bridge, askId, "TelegramAskButtons", extra, fetchImpl, extra.signal, {
|
|
765
822
|
chat_id: result.chat.id,
|
|
766
823
|
message_id: result.message_id,
|
|
@@ -787,24 +844,36 @@ function registerTelegramAskTool(server, settings, client, adapter, fetchImpl) {
|
|
|
787
844
|
* shown inline). Both accept the file as base64 `data` (with a `filename`) OR a
|
|
788
845
|
* workspace `path` (filename derived from the basename), enforce the adapter
|
|
789
846
|
* allowlist, and bound the size to the adapter's inbound cap before uploading via
|
|
790
|
-
* the adapter-owned sender.
|
|
847
|
+
* the adapter-owned sender. Producing-conversation scope omits `chat_id` from the
|
|
848
|
+
* schema and derives it from trusted request context instead.
|
|
791
849
|
*/
|
|
792
850
|
function registerTelegramSendFileTool(server, settings, client, adapter) {
|
|
851
|
+
const producingConversationScope = settings.sendTools?.scope === "producing-conversation";
|
|
852
|
+
const inputSchema = {
|
|
853
|
+
kind: z.enum(["document", "photo"]).describe("`document` for any file (downloadable), `photo` for an image shown inline."),
|
|
854
|
+
...(producingConversationScope
|
|
855
|
+
? {}
|
|
856
|
+
: {
|
|
857
|
+
chat_id: z
|
|
858
|
+
.union([z.string().min(1), z.number().int()])
|
|
859
|
+
.describe("Telegram chat id from the adapter allowlist."),
|
|
860
|
+
}),
|
|
861
|
+
data: z.string().min(1).optional().describe("Base64-encoded file bytes. Provide this or `path`."),
|
|
862
|
+
path: z.string().min(1).optional().describe("Path to a file to upload (resolved against the agent working dir). Provide this or `data`."),
|
|
863
|
+
filename: z.string().min(1).optional().describe("Filename to present. Required with `data` for a document; derived from `path` otherwise."),
|
|
864
|
+
caption: z.string().min(1).optional().describe("Optional caption shown with the file."),
|
|
865
|
+
};
|
|
793
866
|
server.registerTool("TelegramSendFile", {
|
|
794
867
|
title: "Send Telegram file",
|
|
795
|
-
description:
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
data: z.string().min(1).optional().describe("Base64-encoded file bytes. Provide this or `path`."),
|
|
800
|
-
path: z.string().min(1).optional().describe("Path to a file to upload (resolved against the agent working dir). Provide this or `data`."),
|
|
801
|
-
filename: z.string().min(1).optional().describe("Filename to present. Required with `data` for a document; derived from `path` otherwise."),
|
|
802
|
-
caption: z.string().min(1).optional().describe("Optional caption shown with the file."),
|
|
803
|
-
},
|
|
868
|
+
description: producingConversationScope
|
|
869
|
+
? "Upload and send a file to the Telegram conversation that produced this run. The host binds the destination; provide only the file content or path. Set `kind:\"document\"` to send any file (shown as a downloadable document) or `kind:\"photo\"` to send an image inline. Strict run-output paths are always read through a pinned descriptor."
|
|
870
|
+
: "Upload and send a file to an allowed Telegram chat. Set `kind:\"document\"` to send any file (shown as a downloadable document) or `kind:\"photo\"` to send an image inline. Provide the bytes as base64 `data` (with a `filename` — required for a document), or a workspace `path`. A self-hosted Bot API can stream legacy path uploads.",
|
|
871
|
+
inputSchema,
|
|
804
872
|
}, async (args, extra) => {
|
|
805
873
|
extra.signal.throwIfAborted();
|
|
806
874
|
const kind = args.kind;
|
|
807
|
-
|
|
875
|
+
const requestedChatId = "chat_id" in args ? args.chat_id : undefined;
|
|
876
|
+
const chatId = resolveTelegramSendFileChatId(settings, requestedChatId);
|
|
808
877
|
if ((args.data !== undefined) === (args.path !== undefined)) {
|
|
809
878
|
throw new Error("provide exactly one of `data` (base64) or `path`.");
|
|
810
879
|
}
|
|
@@ -830,15 +899,12 @@ function registerTelegramSendFileTool(server, settings, client, adapter) {
|
|
|
830
899
|
}
|
|
831
900
|
try {
|
|
832
901
|
const sent = await client.sendDocument({
|
|
833
|
-
chat_id:
|
|
902
|
+
chat_id: chatId,
|
|
834
903
|
document: pathToFileURL(uploadPath).href,
|
|
835
904
|
...(args.caption === undefined ? {} : { caption: args.caption }),
|
|
836
905
|
}, { signal: extra.signal });
|
|
837
906
|
const name = basename(uploadPath);
|
|
838
|
-
return
|
|
839
|
-
content: [{ type: "text", text: `Sent ${kind} ${sent.message_id} (${name}) to ${String(sent.chat.id)}.` }],
|
|
840
|
-
structuredContent: { ok: true, chat_id: sent.chat.id, message_id: sent.message_id, filename: name },
|
|
841
|
-
};
|
|
907
|
+
return telegramSendFileResult(producingConversationScope, kind, sent, name);
|
|
842
908
|
}
|
|
843
909
|
catch (error) {
|
|
844
910
|
// Retry buffered exactly once; rethrow anything that isn't a server-side rejection.
|
|
@@ -858,23 +924,49 @@ function registerTelegramSendFileTool(server, settings, client, adapter) {
|
|
|
858
924
|
});
|
|
859
925
|
const result = kind === "document"
|
|
860
926
|
? await client.sendDocument({
|
|
861
|
-
chat_id:
|
|
927
|
+
chat_id: chatId,
|
|
862
928
|
document: bytes,
|
|
863
929
|
filename,
|
|
864
930
|
...(args.caption === undefined ? {} : { caption: args.caption }),
|
|
865
931
|
}, { signal: extra.signal })
|
|
866
932
|
: await client.sendPhoto({
|
|
867
|
-
chat_id:
|
|
933
|
+
chat_id: chatId,
|
|
868
934
|
photo: bytes,
|
|
869
935
|
filename,
|
|
870
936
|
...(args.caption === undefined ? {} : { caption: args.caption }),
|
|
871
937
|
}, { signal: extra.signal });
|
|
872
|
-
return
|
|
873
|
-
content: [{ type: "text", text: `Sent ${kind} ${result.message_id} (${filename}) to ${String(result.chat.id)}.` }],
|
|
874
|
-
structuredContent: { ok: true, chat_id: result.chat.id, message_id: result.message_id, filename },
|
|
875
|
-
};
|
|
938
|
+
return telegramSendFileResult(producingConversationScope, kind, result, filename);
|
|
876
939
|
});
|
|
877
940
|
}
|
|
941
|
+
function resolveTelegramSendFileChatId(settings, requestedChatId) {
|
|
942
|
+
if (settings.sendTools?.scope === "producing-conversation") {
|
|
943
|
+
const producingChatId = telegramChatIdFromConversation(settings.producingConversationId);
|
|
944
|
+
if (producingChatId === undefined) {
|
|
945
|
+
throw new Error("TelegramSendFile: producing Telegram conversation context is unavailable.");
|
|
946
|
+
}
|
|
947
|
+
assertTelegramChatAllowed(settings, producingChatId, "TelegramSendFile");
|
|
948
|
+
return producingChatId;
|
|
949
|
+
}
|
|
950
|
+
if (requestedChatId === undefined) {
|
|
951
|
+
throw new Error("TelegramSendFile: chat_id is required outside producing-conversation scope.");
|
|
952
|
+
}
|
|
953
|
+
assertTelegramChatAllowed(settings, requestedChatId, "TelegramSendFile");
|
|
954
|
+
return requestedChatId;
|
|
955
|
+
}
|
|
956
|
+
function telegramSendFileResult(producingConversationScope, kind, sent, filename) {
|
|
957
|
+
const destination = producingConversationScope
|
|
958
|
+
? "the producing Telegram conversation"
|
|
959
|
+
: String(sent.chat.id);
|
|
960
|
+
return {
|
|
961
|
+
content: [{ type: "text", text: `Sent ${kind} ${sent.message_id} (${filename}) to ${destination}.` }],
|
|
962
|
+
structuredContent: {
|
|
963
|
+
ok: true,
|
|
964
|
+
...(producingConversationScope ? {} : { chat_id: sent.chat.id }),
|
|
965
|
+
message_id: sent.message_id,
|
|
966
|
+
filename,
|
|
967
|
+
},
|
|
968
|
+
};
|
|
969
|
+
}
|
|
878
970
|
/** Resolve the upload bytes + filename from exactly one of base64 `data` or a `path`. */
|
|
879
971
|
async function resolveTelegramFileBytes(input) {
|
|
880
972
|
const hasData = input.data !== undefined;
|
|
@@ -1070,21 +1162,21 @@ function assertSlackChannelAllowed(settings, channel) {
|
|
|
1070
1162
|
}
|
|
1071
1163
|
throw new Error("SlackSendMessage: channel is not allowed by Slack adapter config.");
|
|
1072
1164
|
}
|
|
1073
|
-
function assertTelegramChatAllowed(settings, chatId) {
|
|
1165
|
+
function assertTelegramChatAllowed(settings, chatId, toolName) {
|
|
1074
1166
|
const normalized = String(chatId);
|
|
1075
1167
|
if (settings.sendTools?.scope === "producing-conversation") {
|
|
1076
1168
|
const producingChatId = telegramChatIdFromConversation(settings.producingConversationId);
|
|
1077
1169
|
if (producingChatId === undefined) {
|
|
1078
|
-
throw new Error(
|
|
1170
|
+
throw new Error(`${toolName}: producing Telegram conversation context is unavailable.`);
|
|
1079
1171
|
}
|
|
1080
1172
|
if (normalized !== producingChatId) {
|
|
1081
|
-
throw new Error(
|
|
1173
|
+
throw new Error(`${toolName}: chat_id must match the producing Telegram conversation.`);
|
|
1082
1174
|
}
|
|
1083
1175
|
}
|
|
1084
1176
|
if (settings.allowAllChats || settings.allowedChatIds.includes(normalized)) {
|
|
1085
1177
|
return;
|
|
1086
1178
|
}
|
|
1087
|
-
throw new Error(
|
|
1179
|
+
throw new Error(`${toolName}: chat_id is not allowed by Telegram adapter config.`);
|
|
1088
1180
|
}
|
|
1089
1181
|
function telegramChatIdFromConversation(conversationId) {
|
|
1090
1182
|
if (conversationId === undefined)
|