@terminus-ai/cli 0.0.1
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/LICENSE +21 -0
- package/README.md +1055 -0
- package/bin/agent-discovery.mjs +71 -0
- package/bin/agent-icon.mjs +77 -0
- package/bin/agent-models.mjs +77 -0
- package/bin/agent-type.mjs +51 -0
- package/bin/agentdev.mjs +657 -0
- package/bin/app-route-script.mjs +59 -0
- package/bin/app-runtime-contract.mjs +2 -0
- package/bin/appdev-remote.mjs +346 -0
- package/bin/appdev.mjs +4446 -0
- package/bin/apps.mjs +5512 -0
- package/bin/capability-calls.mjs +437 -0
- package/bin/capsule-data.mjs +260 -0
- package/bin/client.mjs +189 -0
- package/bin/commands.mjs +1194 -0
- package/bin/dev-capsules.mjs +1599 -0
- package/bin/dev-contract.mjs +262 -0
- package/bin/dev-data.mjs +287 -0
- package/bin/dev-members.mjs +18 -0
- package/bin/dev-net.mjs +316 -0
- package/bin/dev-notification-popup.mjs +628 -0
- package/bin/dev-ports.mjs +567 -0
- package/bin/dev-server-binding.mjs +35 -0
- package/bin/dev-server-ops.mjs +1086 -0
- package/bin/dev-ui/IoskeleyMono-400.woff2 +0 -0
- package/bin/dev-ui/IoskeleyMono-600.woff2 +0 -0
- package/bin/dev-ui/OFL.txt +92 -0
- package/bin/dev-ui/agent-robot.webp +0 -0
- package/bin/dev-ui/app.js +5217 -0
- package/bin/dev-ui/highlight.js +195 -0
- package/bin/dev-ui/index.html +34 -0
- package/bin/dev-ui/style.css +3640 -0
- package/bin/devlint.mjs +112 -0
- package/bin/devserver.mjs +2127 -0
- package/bin/devtriggers.mjs +367 -0
- package/bin/endpoints.mjs +156 -0
- package/bin/errors.mjs +61 -0
- package/bin/files.mjs +169 -0
- package/bin/horizontal-capabilities/v1/contract.json +280 -0
- package/bin/http.mjs +500 -0
- package/bin/lint-manifests/justbash-commands.json +88 -0
- package/bin/lint-manifests/python-stdlib.json +295 -0
- package/bin/login-page.mjs +488 -0
- package/bin/schedules.mjs +664 -0
- package/bin/server-sandbox.mjs +204 -0
- package/bin/servicedev.mjs +425 -0
- package/bin/sync.mjs +357 -0
- package/bin/terminus.js +3666 -0
- package/bin/toolchain.mjs +125 -0
- package/bin/vendor/app-runtime-v1/app-host.json +124 -0
- package/bin/vendor/app-runtime-v1/capability-calls.json +412 -0
- package/bin/vendor/app-runtime-v1/doors.json +2867 -0
- package/bin/vendor/appd/node-harness.mjs +209 -0
- package/bin/vendor/appd/python-harness.py +12 -0
- package/bin/vendor/appd/server-protocol.json +84 -0
- package/bin/vendor/where.mjs +541 -0
- package/bin/versioning.mjs +72 -0
- package/bin/write-rules.mjs +398 -0
- package/package.json +41 -0
package/bin/files.mjs
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem and hashing helpers shared by every command module. Like
|
|
3
|
+
* client.mjs this file knows nothing about commands or the API.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { createReadStream } from "node:fs";
|
|
8
|
+
import { mkdir, readdir, stat, writeFile } from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
|
|
11
|
+
export async function exists(candidate) {
|
|
12
|
+
try {
|
|
13
|
+
await stat(candidate);
|
|
14
|
+
return true;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** SHA-256 of `bytes`; `encoding` "buffer" returns the raw digest. */
|
|
21
|
+
export function sha256(bytes, encoding = "hex") {
|
|
22
|
+
const hash = createHash("sha256").update(bytes);
|
|
23
|
+
return encoding === "buffer" ? hash.digest() : hash.digest(encoding);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function pathCompare(left, right) {
|
|
27
|
+
if (left === right) return 0;
|
|
28
|
+
return left < right ? -1 : 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Slash-separated path relative to `root`, the shape every package index uses. */
|
|
32
|
+
export function relativePosix(root, absolute) {
|
|
33
|
+
return path.relative(root, absolute).split(path.sep).join("/");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Recursively list the regular files below `root` as `{ path, absolute, name }`
|
|
38
|
+
* sorted by relative path. `skip(relative, dirent)` prunes before descending
|
|
39
|
+
* (ignored directories are never read); `onSymlink(relative)` lets callers
|
|
40
|
+
* reject links — by default links are simply not followed.
|
|
41
|
+
*/
|
|
42
|
+
export async function walkTree(root, { skip = () => false, onSymlink = null } = {}) {
|
|
43
|
+
const out = [];
|
|
44
|
+
async function visit(dir) {
|
|
45
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
46
|
+
const absolute = path.join(dir, entry.name);
|
|
47
|
+
const relative = relativePosix(root, absolute);
|
|
48
|
+
if (skip(relative, entry)) continue;
|
|
49
|
+
if (entry.isSymbolicLink()) {
|
|
50
|
+
onSymlink?.(relative);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
await visit(absolute);
|
|
55
|
+
} else if (entry.isFile()) {
|
|
56
|
+
out.push({ path: relative, absolute, name: entry.name });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
await visit(root);
|
|
61
|
+
out.sort((left, right) => pathCompare(left.path, right.path));
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Compile one gitignore-style pattern into a RegExp over slash paths:
|
|
67
|
+
* `**` spans directories, `*` stays inside a segment, a trailing `/` means
|
|
68
|
+
* "the directory and everything below", and a pattern without a leading `/`
|
|
69
|
+
* matches at any depth. (`path.matchesGlob` is still experimental on Node 22
|
|
70
|
+
* and prints a warning on first use, so the CLI keeps its own matcher.)
|
|
71
|
+
*/
|
|
72
|
+
const GLOB_CACHE = new Map();
|
|
73
|
+
|
|
74
|
+
export function globToRegExp(pattern) {
|
|
75
|
+
const key = String(pattern);
|
|
76
|
+
let compiled = GLOB_CACHE.get(key);
|
|
77
|
+
if (compiled) return compiled;
|
|
78
|
+
let source = key.trim().replace(/^\/+/, "").replace(/\/+$/, "/**");
|
|
79
|
+
source = source.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
80
|
+
source = source.replaceAll("**", "\0").replaceAll("*", "[^/]*").replaceAll("\0", ".*");
|
|
81
|
+
compiled = new RegExp(`^(?:${source}|.*/${source})$`);
|
|
82
|
+
GLOB_CACHE.set(key, compiled);
|
|
83
|
+
return compiled;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Stream `absolute` once, producing its SHA-256, byte length, and whether
|
|
87
|
+
* it decodes as UTF-8 text (`textCandidate` gates the decode attempt). */
|
|
88
|
+
export async function inspectFile(absolute, textCandidate = true) {
|
|
89
|
+
const hash = createHash("sha256");
|
|
90
|
+
let sizeBytes = 0;
|
|
91
|
+
let text = textCandidate;
|
|
92
|
+
const decoder = text ? new TextDecoder("utf-8", { fatal: true }) : null;
|
|
93
|
+
for await (const chunk of createReadStream(absolute)) {
|
|
94
|
+
hash.update(chunk);
|
|
95
|
+
sizeBytes += chunk.length;
|
|
96
|
+
if (text) {
|
|
97
|
+
if (chunk.includes(0)) {
|
|
98
|
+
text = false;
|
|
99
|
+
} else {
|
|
100
|
+
try {
|
|
101
|
+
decoder.decode(chunk, { stream: true });
|
|
102
|
+
} catch {
|
|
103
|
+
text = false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (text) {
|
|
109
|
+
try {
|
|
110
|
+
decoder.decode();
|
|
111
|
+
} catch {
|
|
112
|
+
text = false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { sha256: hash.digest("hex"), sizeBytes, text };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Run `task` over `items` with at most `concurrency` in flight; results come
|
|
119
|
+
* back in input order. */
|
|
120
|
+
export async function runConcurrent(items, concurrency, task) {
|
|
121
|
+
const results = new Array(items.length);
|
|
122
|
+
let cursor = 0;
|
|
123
|
+
const workers = Array.from(
|
|
124
|
+
{ length: Math.min(concurrency, items.length) },
|
|
125
|
+
async () => {
|
|
126
|
+
while (cursor < items.length) {
|
|
127
|
+
const index = cursor;
|
|
128
|
+
cursor += 1;
|
|
129
|
+
results[index] = await task(items[index], index);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
await Promise.all(workers);
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Everything the CLI keeps for one project, in one folder: the working
|
|
138
|
+
* copy's sync record beside whatever `terminus dev` made. */
|
|
139
|
+
export const TERMINUS_DIRECTORY = ".terminus";
|
|
140
|
+
|
|
141
|
+
/** Where `terminus dev` keeps everything it makes on this machine: the
|
|
142
|
+
* SQLite capsules, their object storage, and an agent's workspace. It is
|
|
143
|
+
* the disposable half — `--fresh` empties exactly this — which is why it
|
|
144
|
+
* sits under its own name rather than beside the sync record. */
|
|
145
|
+
export const DEV_DIRECTORY = path.join(TERMINUS_DIRECTORY, "dev");
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Make `<project>/.terminus/dev`, under a `.terminus/` that ignores itself,
|
|
149
|
+
* and answer with it.
|
|
150
|
+
*
|
|
151
|
+
* Git reads nested ignore files, so the databases and objects a dev run
|
|
152
|
+
* writes stay out of the developer's repository without the CLI editing the
|
|
153
|
+
* `.gitignore` they wrote. `writeSyncRecord` writes the same file; whichever
|
|
154
|
+
* runs first is enough.
|
|
155
|
+
*
|
|
156
|
+
* It takes the PROJECT directory, not the dev folder: everything it writes
|
|
157
|
+
* is then under a path it was handed. Deriving `.terminus/` by climbing out
|
|
158
|
+
* of a folder passed in is how a caller with a shallower path writes to the
|
|
159
|
+
* root of the disk.
|
|
160
|
+
*/
|
|
161
|
+
export async function ensureDevDirectory(projectDir) {
|
|
162
|
+
const dev = path.join(projectDir, DEV_DIRECTORY);
|
|
163
|
+
await mkdir(dev, { recursive: true });
|
|
164
|
+
// The ignore file sits at .terminus/, which covers the sync record and
|
|
165
|
+
// everything dev writes under it.
|
|
166
|
+
const ignore = path.join(projectDir, TERMINUS_DIRECTORY, ".gitignore");
|
|
167
|
+
if (!(await exists(ignore))) await writeFile(ignore, "*\n");
|
|
168
|
+
return dev;
|
|
169
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"artifact_contract": {
|
|
4
|
+
"field": "capabilities.artifacts",
|
|
5
|
+
"status": "contract_only",
|
|
6
|
+
"relationships": ["uses", "extends", "delegates", "communicates", "references"],
|
|
7
|
+
"note": "Only skill references execute today; every other edge is reserved metadata."
|
|
8
|
+
},
|
|
9
|
+
"capabilities": [
|
|
10
|
+
{
|
|
11
|
+
"id": "maps",
|
|
12
|
+
"version": "1.0.0",
|
|
13
|
+
"title": "Maps",
|
|
14
|
+
"summary": "Provider-neutral map rendering across raster (OpenStreetMap, Google, Apple) and vector (MapLibre GL over OpenFreeMap, Mapbox) lanes, with search, places, marks, 3D, directions helpers, and platform-brokered geocoding.",
|
|
15
|
+
"availability": ["app"],
|
|
16
|
+
"surfaces": {
|
|
17
|
+
"module": "assets/module.js",
|
|
18
|
+
"stylesheet": "assets/style.css",
|
|
19
|
+
"modules": {
|
|
20
|
+
"leaflet": {
|
|
21
|
+
"version": "1.9.4",
|
|
22
|
+
"asset": "assets/leaflet.js",
|
|
23
|
+
"dependencies": ["assets/leaflet.css"],
|
|
24
|
+
"license": "assets/LICENSE.leaflet.txt"
|
|
25
|
+
},
|
|
26
|
+
"maplibre": {
|
|
27
|
+
"version": "6.7.0",
|
|
28
|
+
"asset": "assets/maplibre-gl.mjs",
|
|
29
|
+
"dependencies": [
|
|
30
|
+
"assets/maplibre-gl-shared.mjs",
|
|
31
|
+
"assets/maplibre-gl-worker.mjs",
|
|
32
|
+
"assets/maplibre-gl.css"
|
|
33
|
+
],
|
|
34
|
+
"license": "assets/LICENSE.maplibre.txt"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"assets": ["assets/styles.json"],
|
|
38
|
+
"operations": ["directions-url", "geocode", "provider-session"]
|
|
39
|
+
},
|
|
40
|
+
"pricing": {
|
|
41
|
+
"geocode": { "openstreetmap": "0", "mapbox": "0.002" },
|
|
42
|
+
"provider-session": { "mapbox": "0.01" }
|
|
43
|
+
},
|
|
44
|
+
"runtime_policy": {
|
|
45
|
+
"connect_src": [
|
|
46
|
+
"https://nominatim.openstreetmap.org",
|
|
47
|
+
"https://maps.googleapis.com",
|
|
48
|
+
"https://cdn.apple-mapkit.com",
|
|
49
|
+
"https://tiles.openfreemap.org",
|
|
50
|
+
"https://elevation-tiles-prod.s3.amazonaws.com",
|
|
51
|
+
"https://api.mapbox.com",
|
|
52
|
+
"https://*.tiles.mapbox.com"
|
|
53
|
+
],
|
|
54
|
+
"img_src": [
|
|
55
|
+
"https://tile.openstreetmap.org",
|
|
56
|
+
"https://*.tile.openstreetmap.org",
|
|
57
|
+
"https://maps.googleapis.com",
|
|
58
|
+
"https://maps.gstatic.com",
|
|
59
|
+
"https://*.apple-mapkit.com",
|
|
60
|
+
"https://tiles.openfreemap.org",
|
|
61
|
+
"https://elevation-tiles-prod.s3.amazonaws.com",
|
|
62
|
+
"https://api.mapbox.com",
|
|
63
|
+
"https://*.tiles.mapbox.com"
|
|
64
|
+
],
|
|
65
|
+
"script_src": [
|
|
66
|
+
"https://maps.googleapis.com",
|
|
67
|
+
"https://cdn.apple-mapkit.com"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": "external-previews",
|
|
73
|
+
"version": "1.0.0",
|
|
74
|
+
"title": "External previews",
|
|
75
|
+
"summary": "Consent-scoped image previews and privacy-enhanced embedded media.",
|
|
76
|
+
"availability": ["app"],
|
|
77
|
+
"surfaces": {
|
|
78
|
+
"operations": []
|
|
79
|
+
},
|
|
80
|
+
"runtime_policy": {
|
|
81
|
+
"frame_src": [
|
|
82
|
+
"https://www.youtube-nocookie.com"
|
|
83
|
+
],
|
|
84
|
+
"img_src": [
|
|
85
|
+
"https://i.ytimg.com"
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "calendar",
|
|
91
|
+
"version": "1.0.0",
|
|
92
|
+
"title": "Calendar and time",
|
|
93
|
+
"summary": "Calendar interchange and timezone-safe date helpers.",
|
|
94
|
+
"availability": ["app"],
|
|
95
|
+
"surfaces": {
|
|
96
|
+
"module": "assets/module.js",
|
|
97
|
+
"operations": ["parse-ics"]
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "rendering",
|
|
102
|
+
"version": "1.0.0",
|
|
103
|
+
"title": "Rendering",
|
|
104
|
+
"summary": "A browser rendering substrate with Canvas, WebGL2, WebGPU feature negotiation, and platform-served Three.js.",
|
|
105
|
+
"availability": ["app"],
|
|
106
|
+
"surfaces": {
|
|
107
|
+
"module": "assets/module.js",
|
|
108
|
+
"modules": {
|
|
109
|
+
"three": {
|
|
110
|
+
"version": "0.185.1",
|
|
111
|
+
"asset": "assets/three.module.min.js",
|
|
112
|
+
"dependencies": ["assets/three.core.min.js"],
|
|
113
|
+
"license": "assets/LICENSE.three.txt"
|
|
114
|
+
},
|
|
115
|
+
"gltf": {
|
|
116
|
+
"version": "0.185.1",
|
|
117
|
+
"asset": "assets/gltf.module.min.js",
|
|
118
|
+
"dependencies": ["assets/three.module.min.js", "assets/three.core.min.js"],
|
|
119
|
+
"license": "assets/LICENSE.three.txt"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "fonts",
|
|
126
|
+
"version": "1.0.0",
|
|
127
|
+
"title": "Fonts",
|
|
128
|
+
"summary": "Platform-served font faces and stable CSS variables for artifact interfaces.",
|
|
129
|
+
"availability": ["app"],
|
|
130
|
+
"surfaces": {
|
|
131
|
+
"stylesheet": "assets/fonts.css"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "web-search",
|
|
136
|
+
"version": "1.0.0",
|
|
137
|
+
"title": "Web search",
|
|
138
|
+
"summary": "Public web search, brokered server-side through the web_search system tool's routed provider service (for example @terminus/brave-search): the platform holds the provider credential and spends the caller's shared per-user daily web budget, so no search origin reaches the page and no runtime policy is contributed. On the agent plane this same capability is the web_search tool; both planes call one broker.",
|
|
139
|
+
"availability": ["app", "agent"],
|
|
140
|
+
"agent_tool": "web_search",
|
|
141
|
+
"surfaces": {
|
|
142
|
+
"operations": ["search"]
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "web-fetch",
|
|
147
|
+
"version": "1.0.0",
|
|
148
|
+
"title": "Web fetch",
|
|
149
|
+
"summary": "SSRF-guarded public text fetch through the platform gateway, spending the caller's shared per-user daily web budget. Agent-plane only: on the agent plane this capability is the web_fetch tool; browser apps fetch public text through network_proxy (net.fetch) instead, so no app operation exists.",
|
|
150
|
+
"availability": ["agent"],
|
|
151
|
+
"agent_tool": "web_fetch",
|
|
152
|
+
"surfaces": {
|
|
153
|
+
"operations": ["fetch"]
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "bash",
|
|
158
|
+
"version": "1.0.0",
|
|
159
|
+
"title": "Shell execution",
|
|
160
|
+
"summary": "Bounded shell programs in the platform's VM-free isolate (just-bash in bashd): ~80 text-processing coreutils over the agent's own workspace (writable root and output/; package files ship read-only in place). No network, package managers, or native binaries; every run is receipted and budgeted per turn. Agent plane only: on the agent plane this capability is the bash tool.",
|
|
161
|
+
"availability": ["agent"],
|
|
162
|
+
"agent_tool": "bash",
|
|
163
|
+
"surfaces": {
|
|
164
|
+
"operations": ["exec"]
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"id": "python",
|
|
169
|
+
"version": "1.0.0",
|
|
170
|
+
"title": "Python execution",
|
|
171
|
+
"summary": "Short standard-library-only CPython 3.13 programs in the platform's WebAssembly isolate, over the agent's lane workspace. No pip, subprocess, network, or native extensions; every run is receipted and budgeted per turn. Agent plane only: on the agent plane this capability is the python tool.",
|
|
172
|
+
"availability": ["agent"],
|
|
173
|
+
"agent_tool": "python",
|
|
174
|
+
"surfaces": {
|
|
175
|
+
"operations": ["exec"]
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "node",
|
|
180
|
+
"version": "1.0.0",
|
|
181
|
+
"title": "JavaScript execution",
|
|
182
|
+
"summary": "Short JavaScript modules on the platform's agentOS V8/WASM isolate, over the agent's lane workspace. No network, npm install, host environment, or native binaries; every run is receipted and budgeted per turn. Agent plane only: on the agent plane this capability is the node tool.",
|
|
183
|
+
"availability": ["agent"],
|
|
184
|
+
"agent_tool": "node",
|
|
185
|
+
"surfaces": {
|
|
186
|
+
"operations": ["exec"]
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "watches",
|
|
191
|
+
"version": "1.0.0",
|
|
192
|
+
"title": "Watches",
|
|
193
|
+
"summary": "Self-managed source tracking: the agent may list, create, adjust, and remove its own page watches for the installation it is talking in — the URL, extraction pattern, poll interval, wake prompt, and an optional numeric condition (percent move, or crossing below/above a level) the platform evaluates with no model spend, waking the agent only when the condition trips. Watches poll public https sources on a 15-minute floor, a repeatedly failing watch pauses itself, and the installer can disable any watch. Agent plane only: on the agent plane this capability is the manage_watches tool.",
|
|
194
|
+
"availability": ["agent"],
|
|
195
|
+
"agent_tool": "manage_watches",
|
|
196
|
+
"surfaces": {
|
|
197
|
+
"operations": ["manage"]
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"id": "schedules",
|
|
202
|
+
"version": "1.0.0",
|
|
203
|
+
"title": "Schedules",
|
|
204
|
+
"summary": "Self-managed standing schedules: the agent may list, create, adjust, and remove its own scheduled runs for the installation it is talking in — cadence and wake prompt; every run delivers one compact notification. Schedules stay inside the per-installation schedule cap, a repeatedly failing trigger pauses itself, and the installer can disable any schedule. Agent plane only: on the agent plane this capability is the manage_schedules tool.",
|
|
205
|
+
"availability": ["agent"],
|
|
206
|
+
"agent_tool": "manage_schedules",
|
|
207
|
+
"surfaces": {
|
|
208
|
+
"operations": ["manage"]
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "image-generation",
|
|
213
|
+
"version": "1.0.0",
|
|
214
|
+
"title": "Image generation",
|
|
215
|
+
"summary": "Platform-routed image generation and editing through the image_generation system tool's provider service. Platform surfaces only today: no app or agent declares this entry directly.",
|
|
216
|
+
"availability": ["platform"],
|
|
217
|
+
"surfaces": {
|
|
218
|
+
"operations": ["generate", "edit"]
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": "document-conversion",
|
|
223
|
+
"version": "1.0.0",
|
|
224
|
+
"title": "Document conversion",
|
|
225
|
+
"summary": "Platform-routed document conversion through the document_conversion system tool's provider service (for example anydoc). Platform surfaces only today: no app or agent declares this entry directly.",
|
|
226
|
+
"availability": ["platform"],
|
|
227
|
+
"surfaces": {
|
|
228
|
+
"operations": ["convert"]
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "email-delivery",
|
|
233
|
+
"version": "1.0.0",
|
|
234
|
+
"title": "Email delivery",
|
|
235
|
+
"summary": "Platform-routed email delivery through the email_delivery system tool's provider service, bounded by the provider's recipient allowlist. Platform surfaces only today: no app or agent declares this entry directly.",
|
|
236
|
+
"availability": ["platform"],
|
|
237
|
+
"surfaces": {
|
|
238
|
+
"operations": ["send"]
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
"bundles": [
|
|
243
|
+
{
|
|
244
|
+
"id": "internet",
|
|
245
|
+
"version": "1.0.0",
|
|
246
|
+
"title": "Internet",
|
|
247
|
+
"members": ["web-search", "web-fetch"]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"id": "compute",
|
|
251
|
+
"version": "1.0.0",
|
|
252
|
+
"title": "Compute",
|
|
253
|
+
"members": ["bash", "python", "node"]
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"id": "automation",
|
|
257
|
+
"version": "1.0.0",
|
|
258
|
+
"title": "Automation",
|
|
259
|
+
"members": ["schedules", "watches"]
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"id": "media",
|
|
263
|
+
"version": "1.0.0",
|
|
264
|
+
"title": "Media",
|
|
265
|
+
"members": ["image-generation"]
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"id": "documents",
|
|
269
|
+
"version": "1.0.0",
|
|
270
|
+
"title": "Documents",
|
|
271
|
+
"members": ["document-conversion"]
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"id": "communication",
|
|
275
|
+
"version": "1.0.0",
|
|
276
|
+
"title": "Communication",
|
|
277
|
+
"members": ["email-delivery"]
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|