@intentic/sandbox-contract 1.326.0 → 1.327.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 +24 -12
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/chores.js +29 -20
- package/dist/chores/chores.js.map +1 -1
- package/dist/chores/probes.d.ts +1 -0
- package/dist/chores/probes.d.ts.map +1 -1
- package/dist/chores/probes.js +81 -12
- package/dist/chores/probes.js.map +1 -1
- package/dist/contracts/agent.contract.d.ts +1467 -6
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +2 -2
- package/dist/contracts/agent.contract.js.map +1 -1
- package/dist/contracts/agents.contract.d.ts +1391 -0
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +1 -1
- package/dist/contracts/automations.contract.d.ts +123 -4
- package/dist/contracts/automations.contract.d.ts.map +1 -1
- package/dist/contracts/automations.contract.js +13 -2
- package/dist/contracts/automations.contract.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts +79 -8
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/chores.contract.d.ts +2 -0
- package/dist/contracts/chores.contract.d.ts.map +1 -1
- package/dist/contracts/ci.contract.d.ts +2 -0
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/device.contract.d.ts +52 -0
- package/dist/contracts/device.contract.d.ts.map +1 -1
- package/dist/contracts/device.contract.js +2 -0
- package/dist/contracts/device.contract.js.map +1 -1
- package/dist/contracts/endpoints.contract.d.ts +42 -33
- package/dist/contracts/endpoints.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.js +17 -7
- package/dist/contracts/endpoints.contract.js.map +1 -1
- package/dist/contracts/extensions.contract.d.ts +192 -0
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js +37 -1
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/needs.contract.d.ts +1009 -0
- package/dist/contracts/needs.contract.d.ts.map +1 -1
- package/dist/contracts/pages.contract.d.ts +34 -0
- package/dist/contracts/pages.contract.d.ts.map +1 -0
- package/dist/contracts/pages.contract.js +49 -0
- package/dist/contracts/pages.contract.js.map +1 -0
- package/dist/contracts/phone.contract.d.ts +78 -0
- package/dist/contracts/phone.contract.d.ts.map +1 -0
- package/dist/contracts/phone.contract.js +11 -0
- package/dist/contracts/phone.contract.js.map +1 -0
- package/dist/contracts/privacy.contract.d.ts +20 -0
- package/dist/contracts/privacy.contract.d.ts.map +1 -1
- package/dist/contracts/privacy.contract.js +12 -2
- package/dist/contracts/privacy.contract.js.map +1 -1
- package/dist/contracts/runner.contract.d.ts +648 -127
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.js +1 -1
- package/dist/contracts/runner.contract.js.map +1 -1
- package/dist/contracts/secrets.contract.d.ts +88 -0
- package/dist/contracts/secrets.contract.d.ts.map +1 -1
- package/dist/contracts/secrets.contract.js +20 -1
- package/dist/contracts/secrets.contract.js.map +1 -1
- package/dist/contracts/sessions.contract.d.ts +184 -0
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.d.ts +16 -58
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.js +10 -1
- package/dist/contracts/settings.contract.js.map +1 -1
- package/dist/contracts/system.contract.d.ts +227 -32
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +18 -1
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/documents/conversions.d.ts.map +1 -1
- package/dist/documents/conversions.js +2 -1
- package/dist/documents/conversions.js.map +1 -1
- package/dist/documents/read.d.ts.map +1 -1
- package/dist/documents/read.js +4 -4
- package/dist/documents/read.js.map +1 -1
- package/dist/events/agent-events.d.ts +747 -1
- package/dist/events/agent-events.d.ts.map +1 -1
- package/dist/events/agent-events.js +14 -1
- package/dist/events/agent-events.js.map +1 -1
- package/dist/events/requests.d.ts +40 -0
- package/dist/events/requests.d.ts.map +1 -1
- package/dist/events/requests.js +39 -0
- package/dist/events/requests.js.map +1 -1
- package/dist/events/system-events.d.ts +120 -0
- package/dist/events/system-events.d.ts.map +1 -1
- package/dist/events/transcript.d.ts +1131 -1
- package/dist/events/transcript.d.ts.map +1 -1
- package/dist/events/transcript.js +9 -1
- package/dist/events/transcript.js.map +1 -1
- package/dist/ids/hostnames.d.ts +2 -0
- package/dist/ids/hostnames.d.ts.map +1 -1
- package/dist/ids/hostnames.js +18 -15
- package/dist/ids/hostnames.js.map +1 -1
- package/dist/ids/sandbox-id.d.ts +2 -0
- package/dist/ids/sandbox-id.d.ts.map +1 -0
- package/dist/ids/sandbox-id.js +2 -0
- package/dist/ids/sandbox-id.js.map +1 -0
- package/dist/ids/tunnel-ids.d.ts +1 -1
- package/dist/ids/tunnel-ids.d.ts.map +1 -1
- package/dist/ids/tunnel-ids.js +1 -1
- package/dist/ids/tunnel-ids.js.map +1 -1
- package/dist/index.d.ts +4902 -177
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -9
- package/dist/index.js.map +1 -1
- package/dist/models/agent-catalog.d.ts +0 -1
- package/dist/models/agent-catalog.d.ts.map +1 -1
- package/dist/models/agent-catalog.js +0 -1
- package/dist/models/agent-catalog.js.map +1 -1
- package/dist/models/agent-runtimes.d.ts +1 -1
- package/dist/models/agent-runtimes.d.ts.map +1 -1
- package/dist/models/agent-runtimes.js +1 -1
- package/dist/models/agent-runtimes.js.map +1 -1
- package/dist/models/provider-specs.d.ts +1 -0
- package/dist/models/provider-specs.d.ts.map +1 -1
- package/dist/models/provider-specs.js +11 -0
- package/dist/models/provider-specs.js.map +1 -1
- package/dist/netd/browser-wire.d.ts.map +1 -0
- package/dist/netd/browser-wire.js.map +1 -0
- package/dist/{front → netd}/generated/browser-wire.d.ts +8 -0
- package/dist/netd/generated/browser-wire.d.ts.map +1 -0
- package/dist/netd/generated/browser-wire.js.map +1 -0
- package/dist/{front → netd}/generated/wire.d.ts +20 -11
- package/dist/netd/generated/wire.d.ts.map +1 -0
- package/dist/{front → netd}/generated/wire.js.map +1 -1
- package/dist/netd/netd-wire.d.ts +9 -0
- package/dist/netd/netd-wire.d.ts.map +1 -0
- package/dist/netd/netd-wire.js +8 -0
- package/dist/netd/netd-wire.js.map +1 -0
- package/dist/policy/credential-material.d.ts +2 -0
- package/dist/policy/credential-material.d.ts.map +1 -1
- package/dist/policy/credential-material.js +14 -8
- package/dist/policy/credential-material.js.map +1 -1
- package/dist/policy/message-limits.d.ts +14 -0
- package/dist/policy/message-limits.d.ts.map +1 -0
- package/dist/policy/message-limits.js +15 -0
- package/dist/policy/message-limits.js.map +1 -0
- package/dist/policy/request-status.d.ts.map +1 -1
- package/dist/policy/request-status.js +9 -1
- package/dist/policy/request-status.js.map +1 -1
- package/dist/policy/reserved-servers.d.ts.map +1 -1
- package/dist/policy/reserved-servers.js +1 -0
- package/dist/policy/reserved-servers.js.map +1 -1
- package/dist/policy/turned-away.d.ts.map +1 -1
- package/dist/policy/turned-away.js +2 -0
- package/dist/policy/turned-away.js.map +1 -1
- package/dist/protocol/container-requirements.d.ts.map +1 -1
- package/dist/protocol/container-requirements.js +3 -4
- package/dist/protocol/container-requirements.js.map +1 -1
- package/dist/protocol/doors/host-protocol.d.ts.map +1 -0
- package/dist/protocol/doors/host-protocol.js.map +1 -0
- package/dist/protocol/{listener-protocol.d.ts → doors/listener-protocol.d.ts} +22 -0
- package/dist/protocol/doors/listener-protocol.d.ts.map +1 -0
- package/dist/protocol/doors/listener-protocol.js +38 -0
- package/dist/protocol/doors/listener-protocol.js.map +1 -0
- package/dist/protocol/doors/phone-links.d.ts +16 -0
- package/dist/protocol/doors/phone-links.d.ts.map +1 -0
- package/dist/protocol/doors/phone-links.js +28 -0
- package/dist/protocol/doors/phone-links.js.map +1 -0
- package/dist/protocol/doors/phone-protocol.d.ts +47 -0
- package/dist/protocol/doors/phone-protocol.d.ts.map +1 -0
- package/dist/protocol/doors/phone-protocol.js +33 -0
- package/dist/protocol/doors/phone-protocol.js.map +1 -0
- package/dist/protocol/doors/runner-protocol.d.ts.map +1 -0
- package/dist/protocol/{runner-protocol.js → doors/runner-protocol.js} +1 -1
- package/dist/protocol/doors/runner-protocol.js.map +1 -0
- package/dist/protocol/{webext-links.d.ts → doors/webext-links.d.ts} +1 -0
- package/dist/protocol/doors/webext-links.d.ts.map +1 -0
- package/dist/protocol/{webext-links.js → doors/webext-links.js} +1 -0
- package/dist/protocol/doors/webext-links.js.map +1 -0
- package/dist/protocol/doors/webext-protocol.d.ts.map +1 -0
- package/dist/protocol/doors/webext-protocol.js.map +1 -0
- package/dist/protocol/edge-verdict.d.ts +1 -1
- package/dist/protocol/edge-verdict.d.ts.map +1 -1
- package/dist/protocol/headers.d.ts +4 -0
- package/dist/protocol/headers.d.ts.map +1 -0
- package/dist/protocol/headers.js +4 -0
- package/dist/protocol/headers.js.map +1 -0
- package/dist/protocol/ingress-contract.d.ts +1 -1
- package/dist/protocol/ingress-contract.d.ts.map +1 -1
- package/dist/protocol/ingress-contract.js +1 -5
- package/dist/protocol/ingress-contract.js.map +1 -1
- package/dist/protocol/peer-dial.d.ts.map +1 -1
- package/dist/protocol/peer-dial.js +18 -36
- package/dist/protocol/peer-dial.js.map +1 -1
- package/dist/protocol/raw/extension-protocol.d.ts +47 -0
- package/dist/protocol/raw/extension-protocol.d.ts.map +1 -0
- package/dist/protocol/raw/extension-protocol.js +32 -0
- package/dist/protocol/raw/extension-protocol.js.map +1 -0
- package/dist/protocol/raw/raw-json-routes.d.ts +855 -0
- package/dist/protocol/raw/raw-json-routes.d.ts.map +1 -0
- package/dist/protocol/raw/raw-json-routes.js +28 -0
- package/dist/protocol/raw/raw-json-routes.js.map +1 -0
- package/dist/protocol/{raw-routes.d.ts → raw/raw-routes.d.ts} +50 -3
- package/dist/protocol/raw/raw-routes.d.ts.map +1 -0
- package/dist/protocol/{raw-routes.js → raw/raw-routes.js} +17 -3
- package/dist/protocol/raw/raw-routes.js.map +1 -0
- package/dist/protocol/raw/route-path.d.ts +3 -0
- package/dist/protocol/raw/route-path.d.ts.map +1 -0
- package/dist/protocol/raw/route-path.js +8 -0
- package/dist/protocol/raw/route-path.js.map +1 -0
- package/dist/protocol/route-meta.d.ts +1 -1
- package/dist/protocol/route-meta.d.ts.map +1 -1
- package/dist/protocol/routes.d.ts +1 -0
- package/dist/protocol/routes.d.ts.map +1 -1
- package/dist/protocol/routes.js +8 -0
- package/dist/protocol/routes.js.map +1 -1
- package/dist/protocol/sse.d.ts +2 -1
- package/dist/protocol/sse.d.ts.map +1 -1
- package/dist/protocol/sse.js +23 -12
- package/dist/protocol/sse.js.map +1 -1
- package/dist/protocol/tunnel-bulk.js +1 -1
- package/dist/protocol/tunnel-bulk.js.map +1 -1
- package/dist/protocol/vitals.d.ts +2 -1
- package/dist/protocol/vitals.d.ts.map +1 -1
- package/dist/protocol/vitals.js +1 -0
- package/dist/protocol/vitals.js.map +1 -1
- package/dist/schemas/activity.d.ts +1 -0
- package/dist/schemas/activity.d.ts.map +1 -1
- package/dist/schemas/activity.js.map +1 -1
- package/dist/schemas/agent.d.ts +6 -0
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +9 -4
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents-list.d.ts +404 -0
- package/dist/schemas/agents-list.d.ts.map +1 -0
- package/dist/schemas/agents-list.js +14 -0
- package/dist/schemas/agents-list.js.map +1 -0
- package/dist/schemas/agents.d.ts +203 -0
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +44 -0
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/automations.d.ts +235 -347
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/automations.js +82 -13
- package/dist/schemas/automations.js.map +1 -1
- package/dist/schemas/capabilities.d.ts +43 -8
- package/dist/schemas/capabilities.d.ts.map +1 -1
- package/dist/schemas/capabilities.js +6 -2
- package/dist/schemas/capabilities.js.map +1 -1
- package/dist/schemas/ci.d.ts +4 -0
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js +8 -0
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/devices.d.ts +67 -0
- package/dist/schemas/devices.d.ts.map +1 -1
- package/dist/schemas/devices.js +8 -0
- package/dist/schemas/devices.js.map +1 -1
- package/dist/schemas/engines.d.ts +57 -0
- package/dist/schemas/engines.d.ts.map +1 -1
- package/dist/schemas/engines.js +4 -0
- package/dist/schemas/engines.js.map +1 -1
- package/dist/schemas/extension-updates.d.ts +329 -0
- package/dist/schemas/extension-updates.d.ts.map +1 -1
- package/dist/schemas/extension-updates.js +68 -3
- package/dist/schemas/extension-updates.js.map +1 -1
- package/dist/schemas/git/git.d.ts +11 -0
- package/dist/schemas/git/git.d.ts.map +1 -1
- package/dist/schemas/git/git.js +4 -4
- package/dist/schemas/git/git.js.map +1 -1
- package/dist/schemas/history.d.ts +2 -0
- package/dist/schemas/history.d.ts.map +1 -1
- package/dist/schemas/history.js.map +1 -1
- package/dist/schemas/hosts.d.ts +74 -0
- package/dist/schemas/hosts.d.ts.map +1 -1
- package/dist/schemas/hosts.js +10 -1
- package/dist/schemas/hosts.js.map +1 -1
- package/dist/schemas/loopback-catch.d.ts +1 -0
- package/dist/schemas/loopback-catch.d.ts.map +1 -1
- package/dist/schemas/loopback-catch.js +1 -0
- package/dist/schemas/loopback-catch.js.map +1 -1
- package/dist/schemas/maintenance.d.ts +8 -0
- package/dist/schemas/maintenance.d.ts.map +1 -1
- package/dist/schemas/maintenance.js +6 -0
- package/dist/schemas/maintenance.js.map +1 -1
- package/dist/schemas/members.d.ts +58 -0
- package/dist/schemas/members.d.ts.map +1 -0
- package/dist/schemas/members.js +16 -0
- package/dist/schemas/members.js.map +1 -0
- package/dist/schemas/metrics.d.ts +10 -0
- package/dist/schemas/metrics.d.ts.map +1 -1
- package/dist/schemas/metrics.js +19 -3
- package/dist/schemas/metrics.js.map +1 -1
- package/dist/schemas/needs.d.ts +1159 -1
- package/dist/schemas/needs.d.ts.map +1 -1
- package/dist/schemas/needs.js +25 -3
- package/dist/schemas/needs.js.map +1 -1
- package/dist/schemas/offload.js +1 -1
- package/dist/schemas/offload.js.map +1 -1
- package/dist/schemas/peer-enrollment.d.ts +7 -0
- package/dist/schemas/peer-enrollment.d.ts.map +1 -0
- package/dist/schemas/peer-enrollment.js +6 -0
- package/dist/schemas/peer-enrollment.js.map +1 -0
- package/dist/schemas/phone.d.ts +231 -0
- package/dist/schemas/phone.d.ts.map +1 -0
- package/dist/schemas/phone.js +57 -0
- package/dist/schemas/phone.js.map +1 -0
- package/dist/schemas/privacy.d.ts +41 -0
- package/dist/schemas/privacy.d.ts.map +1 -1
- package/dist/schemas/privacy.js +20 -3
- package/dist/schemas/privacy.js.map +1 -1
- package/dist/schemas/project-delivery.d.ts +94 -0
- package/dist/schemas/project-delivery.d.ts.map +1 -0
- package/dist/schemas/project-delivery.js +35 -0
- package/dist/schemas/project-delivery.js.map +1 -0
- package/dist/schemas/providers/plan-limits.d.ts +7 -0
- package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
- package/dist/schemas/providers/plan-limits.js +22 -1
- package/dist/schemas/providers/plan-limits.js.map +1 -1
- package/dist/schemas/providers/usage.d.ts +1 -2
- package/dist/schemas/providers/usage.d.ts.map +1 -1
- package/dist/schemas/providers/usage.js +1 -2
- package/dist/schemas/providers/usage.js.map +1 -1
- package/dist/schemas/push.d.ts +1 -0
- package/dist/schemas/push.d.ts.map +1 -1
- package/dist/schemas/push.js.map +1 -1
- package/dist/schemas/secrets.d.ts +99 -0
- package/dist/schemas/secrets.d.ts.map +1 -1
- package/dist/schemas/secrets.js +34 -3
- package/dist/schemas/secrets.js.map +1 -1
- package/dist/schemas/settings-history.d.ts +1 -1
- package/dist/schemas/settings-history.d.ts.map +1 -1
- package/dist/schemas/settings-history.js +1 -0
- package/dist/schemas/settings-history.js.map +1 -1
- package/dist/schemas/settings.d.ts +13 -58
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +8 -13
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/terminal.d.ts +32 -0
- package/dist/schemas/terminal.d.ts.map +1 -1
- package/dist/schemas/terminal.js +37 -0
- package/dist/schemas/terminal.js.map +1 -1
- package/dist/schemas/updates.d.ts +1 -0
- package/dist/schemas/updates.d.ts.map +1 -1
- package/dist/schemas/updates.js +4 -0
- package/dist/schemas/updates.js.map +1 -1
- package/dist/schemas/workspace/workspace-search.d.ts +1 -0
- package/dist/schemas/workspace/workspace-search.d.ts.map +1 -1
- package/dist/schemas/workspace/workspace-search.js.map +1 -1
- package/dist/schemas/workspace/workspace-tree.d.ts +3 -0
- package/dist/schemas/workspace/workspace-tree.d.ts.map +1 -1
- package/dist/schemas/workspace/workspace-tree.js +22 -5
- package/dist/schemas/workspace/workspace-tree.js.map +1 -1
- package/dist/state/arrival.d.ts +59 -0
- package/dist/state/arrival.d.ts.map +1 -1
- package/dist/state/arrival.js +17 -0
- package/dist/state/arrival.js.map +1 -1
- package/dist/state/contract-lock.js +2 -2
- package/dist/state/contract-lock.js.map +1 -1
- package/dist/state/definition.d.ts +82 -16
- package/dist/state/definition.d.ts.map +1 -1
- package/dist/state/history-state.d.ts.map +1 -1
- package/dist/state/history-state.js +38 -0
- package/dist/state/history-state.js.map +1 -1
- package/dist/state/runtime-state.d.ts +6 -0
- package/dist/state/runtime-state.d.ts.map +1 -1
- package/dist/state/runtime-state.js +2 -0
- package/dist/state/runtime-state.js.map +1 -1
- package/dist/state/workspace-state.d.ts +24 -6
- package/dist/state/workspace-state.d.ts.map +1 -1
- package/dist/state/workspace-state.js +29 -7
- package/dist/state/workspace-state.js.map +1 -1
- package/dist/text/embed.d.ts +10 -0
- package/dist/text/embed.d.ts.map +1 -1
- package/dist/text/embed.js +25 -0
- package/dist/text/embed.js.map +1 -1
- package/dist/text/pages.d.ts +53 -0
- package/dist/text/pages.d.ts.map +1 -0
- package/dist/text/pages.js +230 -0
- package/dist/text/pages.js.map +1 -0
- package/dist/text/transcript-fold.d.ts +1 -0
- package/dist/text/transcript-fold.d.ts.map +1 -1
- package/dist/text/transcript-fold.js +30 -2
- package/dist/text/transcript-fold.js.map +1 -1
- package/dist/webext/index.d.ts +3 -2
- package/dist/webext/index.d.ts.map +1 -1
- package/dist/webext/index.js +3 -2
- package/dist/webext/index.js.map +1 -1
- package/package.json +77 -22
- package/src/chores/chores.ts +41 -21
- package/src/chores/{probes.test.ts → probes.integration.test.ts} +134 -1
- package/src/chores/probes.ts +128 -14
- package/src/chores/verdict.test.ts +29 -0
- package/src/contracts/agent.contract.ts +2 -2
- package/src/contracts/agents.contract.ts +1 -1
- package/src/contracts/automations.contract.ts +19 -1
- package/src/contracts/device.contract.ts +5 -0
- package/src/contracts/endpoints.contract.ts +32 -26
- package/src/contracts/extensions.contract.ts +49 -0
- package/src/contracts/pages.contract.ts +61 -0
- package/src/contracts/phone.contract.ts +21 -0
- package/src/contracts/privacy.contract.ts +13 -1
- package/src/contracts/runner.contract.ts +1 -1
- package/src/contracts/secrets.contract.ts +25 -0
- package/src/contracts/settings.contract.ts +10 -0
- package/src/contracts/system.contract.ts +26 -0
- package/src/documents/conversions.ts +3 -1
- package/src/documents/read.ts +4 -5
- package/src/events/agent-events.ts +27 -3
- package/src/events/requests.ts +47 -0
- package/src/events/transcript.ts +14 -0
- package/src/ids/hostnames.fixture.json +14 -10
- package/src/ids/hostnames.test.ts +21 -2
- package/src/ids/hostnames.ts +34 -15
- package/src/ids/sandbox-id.ts +3 -0
- package/src/ids/tunnel-ids.ts +1 -2
- package/src/index.ts +29 -12
- package/src/models/agent-catalog.ts +1 -2
- package/src/models/agent-runtimes.ts +12 -6
- package/src/models/provider-specs.test.ts +12 -0
- package/src/models/provider-specs.ts +16 -0
- package/src/{front → netd}/browser-wire.ts +1 -1
- package/src/{front → netd}/generated/browser-wire.json +80 -7
- package/src/{front → netd}/generated/browser-wire.ts +34 -7
- package/src/{front/generated/front-wire.json → netd/generated/netd-wire.json} +103 -41
- package/src/{front → netd}/generated/tunnel.json +15 -1
- package/src/{front → netd}/generated/wire.ts +26 -21
- package/src/netd/netd-wire.ts +24 -0
- package/src/{front → netd}/wire-manifests.test.ts +31 -11
- package/src/policy/credential-material.ts +39 -11
- package/src/policy/message-limits.ts +25 -0
- package/src/policy/request-status.ts +10 -1
- package/src/policy/reserved-servers.ts +3 -2
- package/src/policy/tests/credential-material.test.ts +49 -1
- package/src/policy/tests/message-limits.test.ts +27 -0
- package/src/policy/tests/reserved-servers.test.ts +3 -3
- package/src/policy/turned-away.ts +5 -1
- package/src/protocol/container-requirements.ts +4 -5
- package/src/protocol/{listener-protocol.ts → doors/listener-protocol.ts} +37 -15
- package/src/protocol/doors/phone-links.ts +50 -0
- package/src/protocol/doors/phone-protocol.test.ts +136 -0
- package/src/protocol/doors/phone-protocol.ts +71 -0
- package/src/protocol/{runner-protocol.ts → doors/runner-protocol.ts} +1 -1
- package/src/protocol/{webext-links.ts → doors/webext-links.ts} +4 -0
- package/src/protocol/edge-verdict.ts +1 -1
- package/src/protocol/headers.ts +14 -0
- package/src/protocol/ingress-contract.ts +6 -10
- package/src/protocol/peer-dial.test.ts +83 -4
- package/src/protocol/peer-dial.ts +33 -40
- package/src/protocol/raw/extension-protocol.ts +59 -0
- package/src/protocol/raw/raw-json-routes.ts +61 -0
- package/src/protocol/{raw-routes.ts → raw/raw-routes.ts} +40 -7
- package/src/protocol/raw/route-path.ts +13 -0
- package/src/protocol/route-meta.ts +4 -4
- package/src/protocol/routes.ts +12 -0
- package/src/protocol/sse.test.ts +49 -0
- package/src/protocol/sse.ts +29 -14
- package/src/protocol/tunnel-bulk.test.ts +1 -1
- package/src/protocol/tunnel-bulk.ts +2 -2
- package/src/protocol/vitals.test.ts +7 -7
- package/src/protocol/vitals.ts +12 -7
- package/src/schemas/activity.ts +1 -0
- package/src/schemas/agent.ts +11 -4
- package/src/schemas/agents-list.ts +24 -0
- package/src/schemas/agents.ts +71 -2
- package/src/schemas/automations.ts +126 -24
- package/src/schemas/capabilities.ts +13 -3
- package/src/schemas/ci.ts +10 -0
- package/src/schemas/devices.ts +24 -0
- package/src/schemas/engines.ts +7 -0
- package/src/schemas/extension-updates.ts +93 -3
- package/src/schemas/git/git.ts +15 -4
- package/src/schemas/history.ts +2 -0
- package/src/schemas/hosts.ts +23 -1
- package/src/schemas/loopback-catch.ts +6 -1
- package/src/schemas/maintenance.ts +9 -0
- package/src/schemas/members.ts +33 -0
- package/src/schemas/metrics.ts +21 -3
- package/src/schemas/needs.ts +36 -3
- package/src/schemas/offload.ts +1 -1
- package/src/schemas/peer-enrollment.ts +14 -0
- package/src/schemas/phone.ts +121 -0
- package/src/schemas/privacy.ts +36 -7
- package/src/schemas/project-delivery.ts +78 -0
- package/src/schemas/providers/plan-limits.ts +27 -3
- package/src/schemas/providers/usage.ts +3 -3
- package/src/schemas/push.ts +1 -0
- package/src/schemas/secrets.ts +54 -3
- package/src/schemas/settings-history.ts +2 -0
- package/src/schemas/settings.ts +20 -22
- package/src/schemas/terminal.ts +50 -0
- package/src/schemas/updates.test.ts +47 -0
- package/src/schemas/updates.ts +4 -0
- package/src/schemas/workspace/workspace-search.ts +2 -0
- package/src/schemas/workspace/workspace-tree.ts +40 -12
- package/src/state/arrival.ts +40 -0
- package/src/state/contract-lock.test.ts +1 -1
- package/src/state/contract-lock.ts +5 -5
- package/src/state/history-state.ts +72 -1
- package/src/state/runtime-state.ts +4 -0
- package/src/state/workspace-state.ts +65 -20
- package/src/text/embed.test.ts +21 -1
- package/src/text/embed.ts +50 -3
- package/src/text/pages.test.ts +161 -0
- package/src/text/pages.ts +344 -0
- package/src/text/transcript-fold.test.ts +22 -0
- package/src/text/transcript-fold.ts +41 -2
- package/src/webext/index.ts +3 -2
- package/dist/front/browser-wire.d.ts.map +0 -1
- package/dist/front/browser-wire.js.map +0 -1
- package/dist/front/front-wire.d.ts +0 -6
- package/dist/front/front-wire.d.ts.map +0 -1
- package/dist/front/front-wire.js +0 -5
- package/dist/front/front-wire.js.map +0 -1
- package/dist/front/generated/browser-wire.d.ts.map +0 -1
- package/dist/front/generated/browser-wire.js.map +0 -1
- package/dist/front/generated/wire.d.ts.map +0 -1
- package/dist/protocol/host-protocol.d.ts.map +0 -1
- package/dist/protocol/host-protocol.js.map +0 -1
- package/dist/protocol/listener-protocol.d.ts.map +0 -1
- package/dist/protocol/listener-protocol.js +0 -33
- package/dist/protocol/listener-protocol.js.map +0 -1
- package/dist/protocol/raw-routes.d.ts.map +0 -1
- package/dist/protocol/raw-routes.js.map +0 -1
- package/dist/protocol/request-id.d.ts +0 -2
- package/dist/protocol/request-id.d.ts.map +0 -1
- package/dist/protocol/request-id.js +0 -2
- package/dist/protocol/request-id.js.map +0 -1
- package/dist/protocol/runner-protocol.d.ts.map +0 -1
- package/dist/protocol/runner-protocol.js.map +0 -1
- package/dist/protocol/webext-links.d.ts.map +0 -1
- package/dist/protocol/webext-links.js.map +0 -1
- package/dist/protocol/webext-protocol.d.ts.map +0 -1
- package/dist/protocol/webext-protocol.js.map +0 -1
- package/src/front/front-wire.ts +0 -15
- package/src/protocol/request-id.ts +0 -2
- /package/dist/{front → netd}/browser-wire.d.ts +0 -0
- /package/dist/{front → netd}/browser-wire.js +0 -0
- /package/dist/{front → netd}/generated/browser-wire.js +0 -0
- /package/dist/{front → netd}/generated/wire.js +0 -0
- /package/dist/protocol/{host-protocol.d.ts → doors/host-protocol.d.ts} +0 -0
- /package/dist/protocol/{host-protocol.js → doors/host-protocol.js} +0 -0
- /package/dist/protocol/{runner-protocol.d.ts → doors/runner-protocol.d.ts} +0 -0
- /package/dist/protocol/{webext-protocol.d.ts → doors/webext-protocol.d.ts} +0 -0
- /package/dist/protocol/{webext-protocol.js → doors/webext-protocol.js} +0 -0
- /package/src/protocol/{host-protocol.ts → doors/host-protocol.ts} +0 -0
- /package/src/protocol/{webext-protocol.ts → doors/webext-protocol.ts} +0 -0
package/src/protocol/sse.ts
CHANGED
|
@@ -2,25 +2,40 @@
|
|
|
2
2
|
// a blank line, each carrying one `data: <JSON>` line. Protocol-only (no domain shapes), shared by every
|
|
3
3
|
// consumer of the wire: the web's chat/intentic streams and the ACP bridge's daemon client.
|
|
4
4
|
|
|
5
|
+
// A live daemon writes to a stream at least this often (oRPC's keep-alive comment every 5 s, a heartbeat on the rest), so
|
|
6
|
+
// this long with no bytes means the connection is dead even though nothing closed it.
|
|
7
|
+
export const SSE_IDLE_MS = 120_000;
|
|
8
|
+
|
|
5
9
|
// Yields each raw SSE frame (the text between blank-line separators) as it arrives, reassembling frames split
|
|
6
|
-
// across network chunks.
|
|
7
|
-
|
|
10
|
+
// across network chunks. Ends, cancelling the reader, after `idleMs` of silence, so a reader of a daemon that went quiet
|
|
11
|
+
// without closing (a sleeping laptop's tunnel, a wedged proxy) finishes instead of hanging.
|
|
12
|
+
export async function* sseFrames(body: ReadableStream<Uint8Array>, idleMs: number = SSE_IDLE_MS): AsyncGenerator<string> {
|
|
8
13
|
const reader = body.getReader();
|
|
9
14
|
const decoder = new TextDecoder();
|
|
10
15
|
let buffer = "";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
try {
|
|
17
|
+
for (;;) {
|
|
18
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
19
|
+
const idle = new Promise<"idle">((resolve) => {
|
|
20
|
+
timer = setTimeout(() => resolve("idle"), idleMs);
|
|
21
|
+
});
|
|
22
|
+
// oxlint-disable-next-line eslint/no-await-in-loop -- streaming reader; each chunk must be awaited in order as it arrives
|
|
23
|
+
const result = await Promise.race([reader.read(), idle]);
|
|
24
|
+
clearTimeout(timer);
|
|
25
|
+
if (result === "idle" || result.done) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
buffer += decoder.decode(result.value, { stream: true });
|
|
29
|
+
let separator = buffer.indexOf("\n\n");
|
|
30
|
+
while (separator !== -1) {
|
|
31
|
+
yield buffer.slice(0, separator);
|
|
32
|
+
buffer = buffer.slice(separator + 2);
|
|
33
|
+
separator = buffer.indexOf("\n\n");
|
|
34
|
+
}
|
|
23
35
|
}
|
|
36
|
+
} finally {
|
|
37
|
+
// allow(silent-catch): A stream already errored or closed has nothing left to cancel.
|
|
38
|
+
await reader.cancel().catch(() => undefined);
|
|
24
39
|
}
|
|
25
40
|
}
|
|
26
41
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { servedRoute } from "./routes.js";
|
|
3
|
-
import { RAW_ROUTE_LIST } from "./raw-routes.js";
|
|
3
|
+
import { RAW_ROUTE_LIST } from "./raw/raw-routes.js";
|
|
4
4
|
import { hostOwnerId } from "./ingress-contract.js";
|
|
5
5
|
import { tunnelBulkRoutes } from "./tunnel-bulk.js";
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { RAW_ROUTE_LIST } from "./raw-routes.js";
|
|
1
|
+
import { RAW_ROUTE_LIST } from "./raw/raw-routes.js";
|
|
2
2
|
|
|
3
|
-
// What the daemon announces to the edge as its transfers (RouteMeta `lane`), handed to
|
|
3
|
+
// What the daemon announces to the edge as its transfers (RouteMeta `lane`), handed to netd with the tunnel's door
|
|
4
4
|
// and carried on each of its sockets' upgrades (the tunnel crate's `x-intentic-bulk`), so the edge sends a transfer
|
|
5
5
|
// down the bulk socket and a keystroke never queues behind it on one TCP connection. The edge compiles in nothing of it.
|
|
6
6
|
export const tunnelBulkRoutes = (): string[] =>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { RAW_ROUTES, rawRoutePath } from "./raw-routes.js";
|
|
1
|
+
import { RAW_ROUTES, rawRoutePath } from "./raw/raw-routes.js";
|
|
2
2
|
import { parseVitals, type SandboxVitals, VITALS_PATH } from "./vitals.js";
|
|
3
3
|
|
|
4
4
|
// The JSON browser-wire's own test pins (`vitals_are_the_camel_case_json_the_editor_parses_with_null_for_what_is_unknown`):
|
|
5
|
-
// what
|
|
5
|
+
// what netd writes, the editor reads.
|
|
6
6
|
const RUST_GOLDEN_JSON = `{"node":"restarting","lagMs":null,"restarts":2,"uptimeS":3600,"pressure":{"cpu":12.34,"memory":0.0,"io":1.5}}`;
|
|
7
7
|
|
|
8
8
|
const up: SandboxVitals = { node: "up", lagMs: 12, restarts: 0, uptimeS: 60, pressure: { cpu: 0.29, memory: 0.49, io: 0.88 } };
|
|
9
9
|
|
|
10
|
-
it("reads
|
|
10
|
+
it("reads netd's own answer as it writes it", () => {
|
|
11
11
|
expect(parseVitals(JSON.parse(RUST_GOLDEN_JSON))).toEqual({
|
|
12
12
|
node: "restarting",
|
|
13
13
|
lagMs: null,
|
|
@@ -23,11 +23,11 @@ it("reads a lag or pressure it cannot make out as unknown, and keeps the rest",
|
|
|
23
23
|
const { lagMs: _lag, pressure: _pressure, ...bare } = up;
|
|
24
24
|
expect(parseVitals(bare)).toEqual({ ...bare, lagMs: null, pressure: null });
|
|
25
25
|
expect(parseVitals({ ...up, lagMs: -1, pressure: { cpu: 1 } })).toEqual({ ...up, lagMs: null, pressure: null });
|
|
26
|
-
// A later
|
|
26
|
+
// A later netd's extra fields are not this reader's business.
|
|
27
27
|
expect(parseVitals({ ...up, since: "later" })).toEqual(up);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
it("is undefined for anything that is not
|
|
30
|
+
it("is undefined for anything that is not netd's answer", () => {
|
|
31
31
|
// An older sandbox forwards the path to Node, which answers 404 as JSON, or a preview's HTML page.
|
|
32
32
|
expect(parseVitals({ error: "Not Found" })).toBeUndefined();
|
|
33
33
|
expect(parseVitals("<!doctype html><title>Not found</title>")).toBeUndefined();
|
|
@@ -40,7 +40,7 @@ it("is undefined for anything that is not the front's answer", () => {
|
|
|
40
40
|
expect(parseVitals({ ...up, restarts: "2" })).toBeUndefined();
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it("is a route
|
|
43
|
+
it("is a route netd serves itself, with no credential, before the daemon boots", () => {
|
|
44
44
|
expect(rawRoutePath("GET /system/vitals")).toBe(VITALS_PATH);
|
|
45
|
-
expect(RAW_ROUTES["GET /system/vitals"]).toEqual({ auth: "door", beforeBoot: true,
|
|
45
|
+
expect(RAW_ROUTES["GET /system/vitals"]).toEqual({ auth: "door", beforeBoot: true, netd: true });
|
|
46
46
|
});
|
package/src/protocol/vitals.ts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
// The sandbox's proof of life, which intentic-
|
|
2
|
-
// Node: whether Node is up, how long its event loop takes to answer
|
|
1
|
+
// The sandbox's proof of life, which intentic-netd answers itself on the daemon's own address and never forwards to
|
|
2
|
+
// Node: whether Node is up, how long its event loop takes to answer netd's ping, how often netd restarted it,
|
|
3
3
|
// how long the container has run, and its pressure stall. The daemon's heartbeat on /events rides Node's event loop,
|
|
4
4
|
// so a busy sandbox and a dead one look alike from there; this route tells them apart. The Rust crate `browser-wire`
|
|
5
5
|
// is the definition (SandboxVitals), and wire-manifests.test.ts holds the path here to the manifest it writes.
|
|
6
6
|
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import type { NodeLink, Pressure, SandboxVitals } from "../
|
|
8
|
+
import type { NodeLink, Pressure, SandboxVitals } from "../netd/generated/browser-wire.js";
|
|
9
9
|
|
|
10
10
|
export type { NodeLink, Pressure, SandboxVitals };
|
|
11
11
|
|
|
12
|
-
// A plain GET any origin may read, answered by
|
|
13
|
-
// `
|
|
12
|
+
// A plain GET any origin may read, answered by netd whatever state Node is in. The route is registered as
|
|
13
|
+
// `netd: true` in raw-routes.ts, so the daemon serves none.
|
|
14
14
|
export const VITALS_PATH = "/system/vitals";
|
|
15
15
|
|
|
16
|
+
// Where netd also writes them inside the container, for a host that reaches the container but not its address (the
|
|
17
|
+
// platform through Fly's exec): a daemon that dies before it names netd's ports leaves netd listening on nothing, and
|
|
18
|
+
// this file is then the only count of its restarts. browser-wire's VITALS_FILE.
|
|
19
|
+
export const VITALS_FILE = "/run/intentic/vitals.json";
|
|
20
|
+
|
|
16
21
|
// Every state, so a new one in the Rust enum fails this file's typecheck until it is read here too.
|
|
17
22
|
const NODE_LINKS = { starting: "starting", up: "up", restarting: "restarting" } as const satisfies { readonly [K in NodeLink]: K };
|
|
18
23
|
|
|
@@ -27,10 +32,10 @@ const VitalsSchema = z.object({
|
|
|
27
32
|
pressure: PressureSchema.nullable().catch(null),
|
|
28
33
|
});
|
|
29
34
|
|
|
30
|
-
// A response body as `Response.json()` hands it over: any JSON value, not yet known to be
|
|
35
|
+
// A response body as `Response.json()` hands it over: any JSON value, not yet known to be netd's answer.
|
|
31
36
|
type JsonBody = string | number | boolean | null | readonly JsonBody[] | { readonly [key: string]: JsonBody };
|
|
32
37
|
|
|
33
|
-
//
|
|
38
|
+
// netd's answer, or undefined for anything else: an older sandbox forwards the path to Node, which answers 404 or
|
|
34
39
|
// an HTML page, and an edge in between may answer for a box that is not there.
|
|
35
40
|
export const parseVitals = (body: JsonBody): SandboxVitals | undefined => {
|
|
36
41
|
const parsed = VitalsSchema.safeParse(body);
|
package/src/schemas/activity.ts
CHANGED
|
@@ -101,6 +101,7 @@ export const ActivityConnectionSchema = z.object({
|
|
|
101
101
|
),
|
|
102
102
|
lastError: z.string().optional().describe("The most recent thing that went wrong on it."),
|
|
103
103
|
});
|
|
104
|
+
export type ActivityConnection = z.infer<typeof ActivityConnectionSchema>;
|
|
104
105
|
export const ActivityStatusSchema = z.object({
|
|
105
106
|
connections: z
|
|
106
107
|
.array(ActivityConnectionSchema)
|
package/src/schemas/agent.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { CONVERSATION_ID } from "../ids/conversation-ids.js";
|
|
4
4
|
import { ModelRoleSchema } from "../models/model-roles.js";
|
|
5
5
|
import { NATIVE_PROVIDERS } from "../models/provider-specs.js";
|
|
6
|
-
import { AgentPlacementSchema } from "../protocol/runner-protocol.js";
|
|
6
|
+
import { AgentPlacementSchema } from "../protocol/doors/runner-protocol.js";
|
|
7
7
|
import { MENTION_LIMIT } from "../text/mentions.js";
|
|
8
8
|
import { entryId } from "./internal.js";
|
|
9
9
|
// Agent runtimes the daemon can serve: native providers have dedicated adapters, `endpoint/<id>` names an installed
|
|
@@ -509,6 +509,13 @@ export const QueuedMessageSchema = z.object({
|
|
|
509
509
|
.int()
|
|
510
510
|
.nonnegative()
|
|
511
511
|
.describe("The queue's revision when this message was last written. An edit or a removal names it, and is refused if the message has changed since."),
|
|
512
|
+
until: z
|
|
513
|
+
.number()
|
|
514
|
+
.optional()
|
|
515
|
+
.describe("When this message goes out by itself, in milliseconds: it was scheduled for that time. Each message keeps its own booking."),
|
|
516
|
+
after: ConversationIdSchema.optional().describe(
|
|
517
|
+
"The conversation whose finished work must land before this message goes out by itself, in place of `until`.",
|
|
518
|
+
),
|
|
512
519
|
});
|
|
513
520
|
export type QueuedMessage = z.infer<typeof QueuedMessageSchema>;
|
|
514
521
|
// Why a queue holds its messages rather than letting them go when the conversation is free.
|
|
@@ -520,14 +527,14 @@ export const ConversationQueueSchema = z.object({
|
|
|
520
527
|
items: z.array(QueuedMessageSchema).describe("What waits, in the order it goes out."),
|
|
521
528
|
revision: z.number().int().nonnegative().describe("Moves with every change to the queue, so of two copies the higher is the newer."),
|
|
522
529
|
paused: QueuePauseSchema.optional().describe(
|
|
523
|
-
"Why
|
|
530
|
+
"Why the messages with no booking of their own do not go out by themselves: somebody stopped the turn, or the turn they started was refused before it ran. Resuming lets them go, and so does sending another message. `scheduled` holds nothing: it says messages are booked, and `until` or `after` is the soonest of their bookings, for clients older than per-message bookings. When any message carries its own `until` or `after`, read those instead.",
|
|
524
531
|
),
|
|
525
532
|
until: z
|
|
526
533
|
.number()
|
|
527
534
|
.optional()
|
|
528
|
-
.describe("
|
|
535
|
+
.describe("The soonest booked message's time, in milliseconds. Only on a queue paused as `scheduled`; each message carries its own."),
|
|
529
536
|
after: ConversationIdSchema.optional().describe(
|
|
530
|
-
"The conversation
|
|
537
|
+
"The conversation the first booked message waits for, when none waits for a time. Only on a queue paused as `scheduled`, in place of `until`.",
|
|
531
538
|
),
|
|
532
539
|
});
|
|
533
540
|
export type ConversationQueue = z.infer<typeof ConversationQueueSchema>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AgentSummarySchema } from "./agents.js";
|
|
3
|
+
import { AutomationApprovalSchema } from "./automations.js";
|
|
4
|
+
|
|
5
|
+
// The fleet list: its own module, since it joins conversations (agents.ts) with held automation wakes (automations.ts),
|
|
6
|
+
// and agents.ts reaches automations.ts through needs.ts (a need can propose an automation), so neither may hold it.
|
|
7
|
+
// `rev` is the registry revision this roster was read at: fleet snapshots are last-frame-wins, so the browser drops any
|
|
8
|
+
// roster older than the newest it applied and holds a pending change until a roster past `rev` arrives. `held` is the
|
|
9
|
+
// approvals queue projected onto the board, defaulted for an older daemon's roster.
|
|
10
|
+
export const AgentsListSchema = z.object({
|
|
11
|
+
agents: z.array(AgentSummarySchema).describe("The conversations."),
|
|
12
|
+
rev: z
|
|
13
|
+
.number()
|
|
14
|
+
.describe(
|
|
15
|
+
"Which version of the fleet this is. The fleet is published as whole snapshots, so without a version a list read before a change but delivered after it would silently undo that change. Drop any list older than the newest you have already applied.",
|
|
16
|
+
),
|
|
17
|
+
held: z
|
|
18
|
+
.array(AutomationApprovalSchema)
|
|
19
|
+
.default([])
|
|
20
|
+
.describe(
|
|
21
|
+
"Automations waiting at the door for a yes, put alongside the running conversations so needs-you sits beside working rather than on a page nobody opens.",
|
|
22
|
+
),
|
|
23
|
+
});
|
|
24
|
+
export type AgentsList = z.infer<typeof AgentsListSchema>;
|
package/src/schemas/agents.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// agents: the conversation fleet
|
|
2
|
+
import { LandingDeliverySchema } from "./project-delivery.js";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
import { AgentHarnessSchema, AgentOriginSchema, AgentProviderSchema, ConversationQueueSchema, ForkedFromSchema } from "./agent.js";
|
|
4
5
|
import { LoopStateSchema } from "./loops.js";
|
|
@@ -6,6 +7,7 @@ import { LimitPolicySchema, RetryPolicySchema, TurnBreakPolicySchema, TurnBreakS
|
|
|
6
7
|
import { KeepWarmSchema } from "./keep-warm.js";
|
|
7
8
|
import { AgentNeedSchema } from "./needs.js";
|
|
8
9
|
import { EMOJI_MAX_LENGTH, isSingleEmoji } from "../text/emoji.js";
|
|
10
|
+
import { ProgramAskSchema } from "../events/requests.js";
|
|
9
11
|
// A fleet agent is any conversation with a registry entry, keyed by conversationId. Isolated ones own a git worktree
|
|
10
12
|
// (branch agent/<id>); workspace conversations have none, but both share one status/activity/cost lifecycle.
|
|
11
13
|
|
|
@@ -115,6 +117,61 @@ export const TurnProofSchema = z.object({
|
|
|
115
117
|
.describe("How many rendered files it changed (pages, components, styles) without looking at the result afterwards. Absent when none."),
|
|
116
118
|
});
|
|
117
119
|
export type TurnProof = z.infer<typeof TurnProofSchema>;
|
|
120
|
+
// How many entries each of a reach's lists carries; past it, the list's `…More` count says how many were left out.
|
|
121
|
+
export const TURN_REACH_LIST_MAX = 10;
|
|
122
|
+
// Where the last turn's work went when it went somewhere other than its own branch, read off what the turn touched and
|
|
123
|
+
// never asked of the model. Lists only the exceptions: a turn whose work all lives on its branch leaves no reach at all.
|
|
124
|
+
export const TurnReachSchema = z.object({
|
|
125
|
+
at: z.number().describe("When the turn that left this ended, in milliseconds."),
|
|
126
|
+
live: z
|
|
127
|
+
.array(
|
|
128
|
+
z.object({
|
|
129
|
+
path: z
|
|
130
|
+
.string()
|
|
131
|
+
.describe(
|
|
132
|
+
"What it wrote, as it named it: relative to the workspace for the sandbox's shared state, absolute for the owner's own checkout.",
|
|
133
|
+
),
|
|
134
|
+
extension: z
|
|
135
|
+
.string()
|
|
136
|
+
.optional()
|
|
137
|
+
.describe("The extension, by its manifest id, when what it changed is the installed copy of one. Absent for anything else."),
|
|
138
|
+
}),
|
|
139
|
+
)
|
|
140
|
+
.max(TURN_REACH_LIST_MAX)
|
|
141
|
+
.optional()
|
|
142
|
+
.describe(
|
|
143
|
+
"Files it changed in place where every conversation reads them, outside its own branch: an installed extension's copy, the sandbox's shared state, the owner's own checkout. Live the moment they were written, never reviewed, and an installed extension's next update replaces them.",
|
|
144
|
+
),
|
|
145
|
+
liveMore: z.number().optional().describe("How many more such files there were beyond the ones listed. Absent when all are listed."),
|
|
146
|
+
stranded: z
|
|
147
|
+
.array(
|
|
148
|
+
z.object({
|
|
149
|
+
dir: z.string().describe("The clone, as a folder relative to its own copy of the workspace."),
|
|
150
|
+
uncommitted: z.number().describe("Files changed in it and never committed."),
|
|
151
|
+
unpushed: z.number().describe("Commits in it its upstream does not have, or that no remote has when it follows none."),
|
|
152
|
+
}),
|
|
153
|
+
)
|
|
154
|
+
.max(TURN_REACH_LIST_MAX)
|
|
155
|
+
.optional()
|
|
156
|
+
.describe(
|
|
157
|
+
"Repositories it cloned inside its own copy and left work in. A clone of its own never rides its land, so what is in one stays there.",
|
|
158
|
+
),
|
|
159
|
+
strandedMore: z.number().optional().describe("How many more such clones there were beyond the ones listed. Absent when all are listed."),
|
|
160
|
+
published: z
|
|
161
|
+
.array(
|
|
162
|
+
z.object({
|
|
163
|
+
dir: z.string().optional().describe("The folder it pushed from, as the command named it. Absent for its own working folder."),
|
|
164
|
+
remote: z.string().optional().describe("The remote it pushed to, as the command named it. Absent when the command named none."),
|
|
165
|
+
branch: z.string().optional().describe("The branch it pushed to, as the command named it. Absent when the command named none."),
|
|
166
|
+
command: z.string().describe("The push itself, trimmed to one line."),
|
|
167
|
+
}),
|
|
168
|
+
)
|
|
169
|
+
.max(TURN_REACH_LIST_MAX)
|
|
170
|
+
.optional()
|
|
171
|
+
.describe("Pushes it made with git that went through: work it sent out of the sandbox itself, never through a land."),
|
|
172
|
+
publishedMore: z.number().optional().describe("How many more such pushes there were beyond the ones listed. Absent when all are listed."),
|
|
173
|
+
});
|
|
174
|
+
export type TurnReach = z.infer<typeof TurnReachSchema>;
|
|
118
175
|
// A landing's commit message: subject plus the two trailer sentences a changelog repo gets. One schema, not three
|
|
119
176
|
// duplicated fields, since both the live roster and the review carrier must read the same shape and can't disagree.
|
|
120
177
|
export const LandedMessageSchema = z.object({
|
|
@@ -440,6 +497,9 @@ export const AgentSummarySchema = z.object({
|
|
|
440
497
|
.object({
|
|
441
498
|
requestId: z.string().describe("Which request this is: the id an answer to it names."),
|
|
442
499
|
ask: z.string().describe("What it asks to do, on one line: the runtime's own sentence, else the tool's short name."),
|
|
500
|
+
program: ProgramAskSchema.optional().describe(
|
|
501
|
+
"The program it is holding, as its own request shows it, so the card can show what would run before anyone answers. Absent on a request about no program.",
|
|
502
|
+
),
|
|
443
503
|
})
|
|
444
504
|
.optional()
|
|
445
505
|
.describe(
|
|
@@ -460,6 +520,11 @@ export const AgentSummarySchema = z.object({
|
|
|
460
520
|
.describe(
|
|
461
521
|
"The last attempt to bring its work into the workspace failed, and why. Cleared by the next land that goes through. Absent when nothing failed, and from a sandbox older than it.",
|
|
462
522
|
),
|
|
523
|
+
// The land's own last word on the owner's folder, for a project attached to this computer's sandbox: written there,
|
|
524
|
+
// partly kept out, waiting for the computer, or refused (schemas/project-delivery.ts).
|
|
525
|
+
delivery: LandingDeliverySchema.optional().describe(
|
|
526
|
+
"What became of its last land in the folder on the owner's computer, for a project folder attached to this computer's sandbox. Absent for any other land, and from a sandbox older than it.",
|
|
527
|
+
),
|
|
463
528
|
// Only the causes that still hold, re-read live (conversations/land/standing.ts), never the stored report's own list: a
|
|
464
529
|
// blocker the user has since cleared is not something to offer them an action about.
|
|
465
530
|
conflictCauses: z
|
|
@@ -477,6 +542,11 @@ export const AgentSummarySchema = z.object({
|
|
|
477
542
|
proof: TurnProofSchema.optional().describe(
|
|
478
543
|
"What its last turn showed of its work: whether a check it ran passed after its last edit, and whether it looked at interface files it changed. Absent until a turn that edited or checked anything has ended.",
|
|
479
544
|
),
|
|
545
|
+
// Written by the turn's own settle from its tool calls and a read of the clones and installs it could have touched;
|
|
546
|
+
// replaced by every turn, so it says where the LAST turn's work went.
|
|
547
|
+
reach: TurnReachSchema.optional().describe(
|
|
548
|
+
"Where its last turn's work went when it went somewhere besides its own branch: files changed live outside it, clones of its own holding work that will not land, pushes it made itself. Absent when everything it did is on its branch.",
|
|
549
|
+
),
|
|
480
550
|
// Completed turns and lifetime tool calls, the card's msgs/tools counters.
|
|
481
551
|
turns: z.number().optional().describe("Turns it has finished."),
|
|
482
552
|
toolUses: z.number().optional().describe("Tools it has used, over its whole life."),
|
|
@@ -657,8 +727,7 @@ export type LandedRemover = NonNullable<NonNullable<AgentSummary["landedPresence
|
|
|
657
727
|
export type LandFailure = NonNullable<AgentSummary["landFailure"]>;
|
|
658
728
|
// The permission a running turn waits on, as a card can answer it.
|
|
659
729
|
export type WaitingPermission = NonNullable<AgentSummary["permissionAsk"]>;
|
|
660
|
-
// AgentsListSchema
|
|
661
|
-
// needs that type declared first.
|
|
730
|
+
// AgentsListSchema lives in agents-list.ts, since the fleet list carries held wakes (automations.ts).
|
|
662
731
|
export const AgentIdSchema = z.object({ id: z.string().min(1).describe("Which conversation.") });
|
|
663
732
|
|
|
664
733
|
// Naming no watch disarms every one, which is what a press made about the whole card means; a press made about one
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// automations: scheduled agent wake-ups (.intentic/config/automations.json)
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { AgentOriginSchema, ModelPinSchema } from "./agent.js";
|
|
4
|
-
import { AgentSummarySchema } from "./agents.js";
|
|
5
4
|
import { entryId } from "./internal.js";
|
|
6
5
|
import { IssuesConfigSchema } from "./issues.js";
|
|
7
6
|
import { ZoneSchema } from "../time/zone.js";
|
|
@@ -124,6 +123,81 @@ export const TriggerSchema = z.discriminatedUnion("kind", [
|
|
|
124
123
|
}),
|
|
125
124
|
]);
|
|
126
125
|
export type Trigger = z.infer<typeof TriggerSchema>;
|
|
126
|
+
// A watch is an automation whose check decides, without a model, whether anything happened: either its `guard` command
|
|
127
|
+
// or one of these ready-made sources, which the daemon checks itself (automations/watch/watch-sources.ts). Only once the check
|
|
128
|
+
// says so does anything run, and what it saw goes with the wake. No source needs an extension, a token or a shell.
|
|
129
|
+
// npm: the registry's view of one package. With `range`, the check passes once a published version satisfies it, and
|
|
130
|
+
// what it saw is that version; without, what it saw is the version under `tag` (latest by default), for `fireOn: change`.
|
|
131
|
+
// github-release: a public repository's newest release (prereleases only when asked), for `fireOn: change`.
|
|
132
|
+
// url: one page, its text or the first `select` match, for `fireOn: change`.
|
|
133
|
+
export const WatchSourceSchema = z.discriminatedUnion("kind", [
|
|
134
|
+
z.object({
|
|
135
|
+
kind: z.literal("npm").describe("A package on the npm registry."),
|
|
136
|
+
package: z.string().min(1).max(214).describe("The package name, scoped or not, like bun or @scope/name."),
|
|
137
|
+
range: z
|
|
138
|
+
.string()
|
|
139
|
+
.min(1)
|
|
140
|
+
.max(200)
|
|
141
|
+
.optional()
|
|
142
|
+
.describe("A semver range, like >=1.4.3. Passes once a published version satisfies it. Prereleases count only when the range names one."),
|
|
143
|
+
tag: z.string().min(1).max(100).optional().describe("Which dist-tag to read without a range. Absent means latest."),
|
|
144
|
+
}),
|
|
145
|
+
z.object({
|
|
146
|
+
kind: z.literal("github-release").describe("The newest release of a public GitHub repository."),
|
|
147
|
+
repo: z
|
|
148
|
+
.string()
|
|
149
|
+
.regex(/^[\w.-]+\/[\w.-]+$/, "repo must look like owner/name")
|
|
150
|
+
.describe("The repository, as owner/name."),
|
|
151
|
+
prereleases: z.boolean().optional().describe("Count prereleases too. Absent means only full releases."),
|
|
152
|
+
}),
|
|
153
|
+
z.object({
|
|
154
|
+
kind: z.literal("url").describe("One web page."),
|
|
155
|
+
url: z.string().url().describe("The page, http or https."),
|
|
156
|
+
select: z
|
|
157
|
+
.string()
|
|
158
|
+
.min(1)
|
|
159
|
+
.max(500)
|
|
160
|
+
.optional()
|
|
161
|
+
.describe("A regular expression; what it matches (its first group, if it has one) is what is watched rather than the whole page's text."),
|
|
162
|
+
}),
|
|
163
|
+
]);
|
|
164
|
+
export type WatchSource = z.infer<typeof WatchSourceSchema>;
|
|
165
|
+
// What a passing check sets off. `agent` (the default) is a new agent with the prompt, as every automation always did;
|
|
166
|
+
// `conversation` continues one that already exists, the way a watch wakes the conversation that armed it, so a plan
|
|
167
|
+
// made weeks ago resumes where it stopped; `notify` runs no model at all, and only tells the owner what the check saw.
|
|
168
|
+
export const AutomationTargetSchema = z.discriminatedUnion("kind", [
|
|
169
|
+
z.object({ kind: z.literal("agent").describe("A new agent, told the prompt and what the check saw.") }),
|
|
170
|
+
z.object({
|
|
171
|
+
kind: z.literal("conversation").describe("An existing conversation, continued with what the check saw and the prompt."),
|
|
172
|
+
conversationId: z.string().min(1).describe("Which conversation."),
|
|
173
|
+
}),
|
|
174
|
+
z.object({ kind: z.literal("notify").describe("No agent: a notification to the owner with what the check saw.") }),
|
|
175
|
+
]);
|
|
176
|
+
export type AutomationTarget = z.infer<typeof AutomationTargetSchema>;
|
|
177
|
+
// `pass` (the default): every check that passes fires. `change`: a check fires only when what it saw differs from what
|
|
178
|
+
// it saw last time, and the first one only records where things stand, so a watch says when something moves rather
|
|
179
|
+
// than that it is still there.
|
|
180
|
+
export const FireOnSchema = z.enum(["pass", "change"]);
|
|
181
|
+
export type FireOn = z.infer<typeof FireOnSchema>;
|
|
182
|
+
// What the daemon remembers of a watch between checks (.intentic/records/automation-watch.json), and what the list
|
|
183
|
+
// shows under it. Values are kept whole up to a bound, so the next check can say what changed.
|
|
184
|
+
export const WatchStateSchema = z.object({
|
|
185
|
+
armedAt: z.number().describe("When it was first checked, in milliseconds."),
|
|
186
|
+
checkedAt: z.number().describe("When it was last checked, in milliseconds."),
|
|
187
|
+
value: z.string().optional().describe("What the last passing check saw. Absent until one has passed."),
|
|
188
|
+
changedAt: z.number().optional().describe("When what it saw last changed, in milliseconds."),
|
|
189
|
+
firedAt: z.number().optional().describe("When it last set something off, in milliseconds."),
|
|
190
|
+
// Why the last check did not pass, when it did not.
|
|
191
|
+
waiting: z.string().optional().describe("What the last check said when it did not pass: what it is still waiting for."),
|
|
192
|
+
});
|
|
193
|
+
export type WatchState = z.infer<typeof WatchStateSchema>;
|
|
194
|
+
// POST /automations/check: one source checked now, nothing remembered.
|
|
195
|
+
export const WatchCheckInputSchema = z.object({ source: WatchSourceSchema.describe("The source to check.") });
|
|
196
|
+
export const WatchCheckResultSchema = z.object({
|
|
197
|
+
pass: z.boolean().describe("Whether the check passes now."),
|
|
198
|
+
saw: z.string().describe("What it saw when it passed, or what it is still waiting for when it did not."),
|
|
199
|
+
});
|
|
200
|
+
export type WatchCheckResult = z.infer<typeof WatchCheckResultSchema>;
|
|
127
201
|
// The Visitor chat widget's settings, present only on `webchat` listener automations. Split into what the widget itself
|
|
128
202
|
// may read (public by construction) and what only the daemon may (turnstileSecret); GET /webchat/<id>/config serves the
|
|
129
203
|
// first group by naming it, never by omitting the second.
|
|
@@ -269,8 +343,38 @@ export const AutomationSchema = z.object({
|
|
|
269
343
|
.min(1)
|
|
270
344
|
.optional()
|
|
271
345
|
.describe(
|
|
272
|
-
"A command run before the wake that decides whether there is anything to do. Skipped by the guard is often the most useful thing an automation can report.",
|
|
346
|
+
"A command run before the wake that decides whether there is anything to do. Skipped by the guard is often the most useful thing an automation can report. What it prints when it passes goes with the wake; $AUTOMATION_STATE names a file it may keep between runs, and $AUTOMATION_LAST holds what it printed last time it passed.",
|
|
273
347
|
),
|
|
348
|
+
// The guard's alternative: a condition the daemon checks itself. Refused at upsert beside a guard, since two checks
|
|
349
|
+
// would leave "what the check saw" meaning two things.
|
|
350
|
+
source: WatchSourceSchema.optional().describe(
|
|
351
|
+
"A ready-made check instead of a guard command: an npm package's version, a GitHub repository's newest release, or a web page.",
|
|
352
|
+
),
|
|
353
|
+
fireOn: FireOnSchema.optional().describe(
|
|
354
|
+
"Fire on every passing check, or only when what the check saw changed since the last one. Absent means every passing check.",
|
|
355
|
+
),
|
|
356
|
+
// Retirement, so a watch never outlives what it was for: `first-fire` switches it off as it fires, the way a one-time
|
|
357
|
+
// wake retires; `expiresAt` switches it off at a deadline and says so.
|
|
358
|
+
until: z
|
|
359
|
+
.enum(["first-fire"])
|
|
360
|
+
.optional()
|
|
361
|
+
.describe("Switch it off the first time it fires, for a watch waiting on one thing. Absent means it keeps firing."),
|
|
362
|
+
expiresAt: z
|
|
363
|
+
.number()
|
|
364
|
+
.int()
|
|
365
|
+
.positive()
|
|
366
|
+
.optional()
|
|
367
|
+
.describe("When it gives up, in milliseconds. Switched off then, and whoever it was for is told it never fired."),
|
|
368
|
+
target: AutomationTargetSchema.optional().describe(
|
|
369
|
+
"What a passing check sets off: a new agent (the default), an existing conversation, or only a notification to the owner.",
|
|
370
|
+
),
|
|
371
|
+
// One line a notification and a woken conversation read; an automation has no title of its own.
|
|
372
|
+
note: z
|
|
373
|
+
.string()
|
|
374
|
+
.min(1)
|
|
375
|
+
.max(200)
|
|
376
|
+
.optional()
|
|
377
|
+
.describe("One line on what it watches for, like 'Bun 1.4.3 is published'. Shown in its notifications."),
|
|
274
378
|
prompt: z.string().min(1).describe("What the woken agent is told."),
|
|
275
379
|
// The Visitor chat widget's settings, `webchat` listener automations only, ignored on every other trigger.
|
|
276
380
|
webchat: WebchatConfigSchema.optional().describe("Settings for the public chat widget, for an automation that answers visitors."),
|
|
@@ -287,15 +391,18 @@ export const AutomationSchema = z.object({
|
|
|
287
391
|
.describe(
|
|
288
392
|
"Narrow the woken turn to these tools. For one driven by an outside message this list is the real boundary, because prompt wording is only advice and an empty toolbox is not.",
|
|
289
393
|
),
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
//
|
|
394
|
+
// Ordered ladder (replaces separate agent/harness/model fields): an automation spends real money unwatched, so it must
|
|
395
|
+
// name what it spends rather than inherit a chat's default. Walked in order at fire time to the first rung that can
|
|
396
|
+
// start; each rung is a whole pin (provider+model+effort+harness together). Required for a new agent, the default
|
|
397
|
+
// target, and refused there at upsert when absent; a conversation target runs on that conversation's own model and a
|
|
398
|
+
// notification runs none, so neither needs one.
|
|
293
399
|
models: z
|
|
294
400
|
.array(ModelPinSchema)
|
|
295
401
|
.min(1)
|
|
296
402
|
.max(10)
|
|
403
|
+
.optional()
|
|
297
404
|
.describe(
|
|
298
|
-
"Which models this automation may run on, best first. Required, and nothing is chosen for you: work that fires while nobody is watching spends a real allowance, so it names the models it spends rather than inheriting one. Tried in order, so a spent account does not silently stop the job.",
|
|
405
|
+
"Which models this automation may run on, best first. Required when it starts a new agent, and nothing is chosen for you: work that fires while nobody is watching spends a real allowance, so it names the models it spends rather than inheriting one. Tried in order, so a spent account does not silently stop the job. Not needed to continue a conversation, which runs on its own model, or to only notify.",
|
|
299
406
|
),
|
|
300
407
|
// Absent means the daemon's pick: the account its conversation runs on for a continuing thread (moved off one that
|
|
301
408
|
// can no longer serve), else the one that can serve with the most room. Named, it is a pin, run whatever its state,
|
|
@@ -341,6 +448,8 @@ export const AutomationApprovalSchema = z.object({
|
|
|
341
448
|
"Where the message came from, kept alongside the payload so an approved wake appears on the board exactly as an automatic one would have.",
|
|
342
449
|
),
|
|
343
450
|
title: z.string().optional().describe("What the conversation would be called."),
|
|
451
|
+
// What the automation's check saw when it passed, so the approved wake carries it as an automatic one would have.
|
|
452
|
+
observed: z.string().optional().describe("What the automation's check saw when it passed, kept so the approved wake is told the same thing."),
|
|
344
453
|
// The thread this wake belongs to, so approving continues it rather than minting a fresh conversation per approved
|
|
345
454
|
// message.
|
|
346
455
|
conversationId: z
|
|
@@ -367,24 +476,10 @@ export const AutomationApprovalSchema = z.object({
|
|
|
367
476
|
),
|
|
368
477
|
});
|
|
369
478
|
export type AutomationApproval = z.infer<typeof AutomationApprovalSchema>;
|
|
370
|
-
|
|
371
|
-
//
|
|
372
|
-
//
|
|
373
|
-
export const
|
|
374
|
-
agents: z.array(AgentSummarySchema).describe("The conversations."),
|
|
375
|
-
rev: z
|
|
376
|
-
.number()
|
|
377
|
-
.describe(
|
|
378
|
-
"Which version of the fleet this is. The fleet is published as whole snapshots, so without a version a list read before a change but delivered after it would silently undo that change. Drop any list older than the newest you have already applied.",
|
|
379
|
-
),
|
|
380
|
-
held: z
|
|
381
|
-
.array(AutomationApprovalSchema)
|
|
382
|
-
.default([])
|
|
383
|
-
.describe(
|
|
384
|
-
"Automations waiting at the door for a yes, put alongside the running conversations so needs-you sits beside working rather than on a page nobody opens.",
|
|
385
|
-
),
|
|
386
|
-
});
|
|
387
|
-
export type AgentsList = z.infer<typeof AgentsListSchema>;
|
|
479
|
+
|
|
480
|
+
// Whether a held wake waits on a person. A countdown hold (`autoRunAt`) releases itself, so counting it would ask the
|
|
481
|
+
// owner about something already about to happen on its own.
|
|
482
|
+
export const awaitsOwner = (wake: Pick<AutomationApproval, "autoRunAt">): boolean => wake.autoRunAt === undefined;
|
|
388
483
|
export const AutomationApprovalsListSchema = z.object({ approvals: z.array(AutomationApprovalSchema).describe("Everything waiting for a yes.") });
|
|
389
484
|
export const AutomationApprovalIdParamSchema = z.object({ id: z.string().describe("Which waiting item.") });
|
|
390
485
|
export const AutomationRunSchema = z.object({
|
|
@@ -406,6 +501,8 @@ export const FIRE_DAILY_MAX_DEFAULT = 200;
|
|
|
406
501
|
export const AutomationSummarySchema = AutomationSchema.extend({
|
|
407
502
|
runs: z.array(AutomationRunSchema),
|
|
408
503
|
nextRun: z.number().optional(),
|
|
504
|
+
// Absent for an automation with no check, and for one never checked.
|
|
505
|
+
watch: WatchStateSchema.optional().describe("What its check saw last and when, for an automation that checks something before it fires."),
|
|
409
506
|
// Door credentials, attached for a maintainer or owner only, never a viewer or a control-token program; kept in the
|
|
410
507
|
// secrets store, not the manifest.
|
|
411
508
|
webhookToken: z
|
|
@@ -484,6 +581,11 @@ export const AutomationTemplateSchema = z.object({
|
|
|
484
581
|
trigger: TriggerSchema,
|
|
485
582
|
// Prefills the guard command (a shell one-liner; non-zero exit skips the wake).
|
|
486
583
|
guard: z.string().min(1).optional(),
|
|
584
|
+
// Prefill a watch: a ready-made check, when it fires, whether it retires, and what it sets off.
|
|
585
|
+
source: WatchSourceSchema.optional(),
|
|
586
|
+
fireOn: FireOnSchema.optional(),
|
|
587
|
+
until: z.enum(["first-fire"]).optional(),
|
|
588
|
+
target: AutomationTargetSchema.optional(),
|
|
487
589
|
// Prefills the countdown hold: each fire waits this long, visibly and cancellably, before starting itself.
|
|
488
590
|
holdForSeconds: z.number().int().positive().optional(),
|
|
489
591
|
prompt: z.string().min(1),
|