@aiaiai-pt/martha-cli 0.68.1 → 0.69.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/CHANGELOG.md +24 -0
- package/dist/index.js +53 -12
- package/package.json +1 -1
- package/skills/martha-cli/SKILL.md +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@aiaiai-pt/martha-cli`. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project adheres to semver — `0.x` releases may include breaking changes between minor versions.
|
|
4
4
|
|
|
5
|
+
## [0.69.0] — 2026-11-13
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `martha definitions apply` preserves the server-supported agent `base_pack_opt_out` flag, allowing narrowly granted specialists such as delegated customer support without restoring broad default tools. This release retains the current published CLI capabilities.
|
|
10
|
+
|
|
11
|
+
## [0.68.4] — 2026-11-09
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- `martha definitions apply` compares a function's `risk_tags` as the server stores them: a legacy spelling (`write`, `delete`, …) matches the canonical tag it maps to, and order no longer matters. It used to report a change on every apply once the server stored the canonical form (MARTHA-602).
|
|
16
|
+
|
|
17
|
+
## [0.68.3] — 2026-11-09
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `martha functions update` and `martha definitions apply` now check the function's `tool` block (the per-tool call timeout, #1833): an update whose `tool` the server did not persist fails instead of reporting success.
|
|
22
|
+
|
|
23
|
+
## [0.68.2] — 2026-11-08
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `martha agents doctor` and `martha agents runner-presence` report runner presence as unknown when the presence registry can't be read (the server sends `present: null, available: false`) or the presence call fails. They used to say "no runner connected", which is wrong during an outage: the runner may be attached.
|
|
28
|
+
|
|
5
29
|
## [0.68.1] — 2026-11-03
|
|
6
30
|
|
|
7
31
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -11244,7 +11244,7 @@ init_config();
|
|
|
11244
11244
|
init_errors();
|
|
11245
11245
|
|
|
11246
11246
|
// src/version.ts
|
|
11247
|
-
var CLI_VERSION = "0.
|
|
11247
|
+
var CLI_VERSION = "0.69.0";
|
|
11248
11248
|
|
|
11249
11249
|
// src/commands/sessions.ts
|
|
11250
11250
|
function relativeTime(iso) {
|
|
@@ -11633,18 +11633,25 @@ async function diagnoseHostRunner(ctx, name) {
|
|
|
11633
11633
|
fix: takeover ? undefined : setupFix
|
|
11634
11634
|
});
|
|
11635
11635
|
let attached = false;
|
|
11636
|
+
let presenceUnknown = false;
|
|
11636
11637
|
let attachedHost;
|
|
11637
11638
|
try {
|
|
11638
11639
|
const pres = await ctx.api.get(`${API_PATH}/runner-presence`);
|
|
11639
11640
|
const p = pres.presence?.[name];
|
|
11640
|
-
|
|
11641
|
+
if (p?.present === null || p?.available === false) {
|
|
11642
|
+
presenceUnknown = true;
|
|
11643
|
+
} else {
|
|
11644
|
+
attached = !!p?.present;
|
|
11645
|
+
}
|
|
11641
11646
|
attachedHost = p?.connections?.[0]?.host;
|
|
11642
|
-
} catch {
|
|
11647
|
+
} catch {
|
|
11648
|
+
presenceUnknown = true;
|
|
11649
|
+
}
|
|
11643
11650
|
checks.push({
|
|
11644
|
-
ok: attached,
|
|
11651
|
+
ok: presenceUnknown ? null : attached,
|
|
11645
11652
|
label: "a runner is attached now",
|
|
11646
|
-
detail: attached ? `host ${attachedHost ?? "?"}` : "no runner connected",
|
|
11647
|
-
fix: attached ? undefined : `on the target machine: martha runner --tools --allow-host-exec (and the server needs CHANNEL_ENABLED=1)`
|
|
11653
|
+
detail: presenceUnknown ? "unknown (presence registry unreachable)" : attached ? `host ${attachedHost ?? "?"}` : "no runner connected",
|
|
11654
|
+
fix: presenceUnknown ? "check Redis connectivity on the Martha server" : attached ? undefined : `on the target machine: martha runner --tools --allow-host-exec (and the server needs CHANNEL_ENABLED=1)`
|
|
11648
11655
|
});
|
|
11649
11656
|
const isHostRunner = hasKey || hostTools.length > 0;
|
|
11650
11657
|
const drivableFromChat = marthaHosted && hasKey && hostTools.length > 0 && grantingClients.length > 0 && takeover;
|
|
@@ -12008,6 +12015,8 @@ Attach it as this agent's host executor:
|
|
|
12008
12015
|
if (p.present && conns.length) {
|
|
12009
12016
|
const hosts = conns.map((c) => c.host || c.connection_id?.slice(0, 8) || "?").join(", ");
|
|
12010
12017
|
console.log(`${source_default.green("● connected")} ${name} ${source_default.dim(`(${hosts})`)}`);
|
|
12018
|
+
} else if (p.present === null || p.available === false) {
|
|
12019
|
+
console.log(`${source_default.yellow("? unknown")} ${name}`);
|
|
12011
12020
|
} else {
|
|
12012
12021
|
console.log(`${source_default.dim("○ disconnected")} ${name}`);
|
|
12013
12022
|
}
|
|
@@ -15902,7 +15911,8 @@ var MUTABLE_FIELDS = {
|
|
|
15902
15911
|
"risk_tags",
|
|
15903
15912
|
"risk_level",
|
|
15904
15913
|
"verification_safe",
|
|
15905
|
-
"idempotent"
|
|
15914
|
+
"idempotent",
|
|
15915
|
+
"tool"
|
|
15906
15916
|
]),
|
|
15907
15917
|
Workflow: new Set([
|
|
15908
15918
|
"description",
|
|
@@ -16146,6 +16156,7 @@ var AGENT_WRITE_FIELDS = new Set([
|
|
|
16146
16156
|
"llm_config",
|
|
16147
16157
|
"loop_config",
|
|
16148
16158
|
"runs_as_chat",
|
|
16159
|
+
"base_pack_opt_out",
|
|
16149
16160
|
"agent_metadata",
|
|
16150
16161
|
"auth_method",
|
|
16151
16162
|
"webhook_url",
|
|
@@ -16330,6 +16341,30 @@ async function computeOperations(defs, api) {
|
|
|
16330
16341
|
}
|
|
16331
16342
|
return ops;
|
|
16332
16343
|
}
|
|
16344
|
+
var EFFECT_TAG_ALIASES = {
|
|
16345
|
+
write: "mutating",
|
|
16346
|
+
delete: "destructive_write",
|
|
16347
|
+
destructive: "destructive_write",
|
|
16348
|
+
host_exec: "host_execution",
|
|
16349
|
+
readonly: "read_only",
|
|
16350
|
+
read: "read_only",
|
|
16351
|
+
payments: "payment",
|
|
16352
|
+
code_execution: "arbitrary_code",
|
|
16353
|
+
fs: "filesystem"
|
|
16354
|
+
};
|
|
16355
|
+
function canonicalEffectTag(tag) {
|
|
16356
|
+
if (typeof tag !== "string")
|
|
16357
|
+
return tag;
|
|
16358
|
+
const key = tag.trim().toLowerCase().replace(/[- ]/g, "_");
|
|
16359
|
+
return EFFECT_TAG_ALIASES[key] ?? key;
|
|
16360
|
+
}
|
|
16361
|
+
function effectTagsMatch(local, remote) {
|
|
16362
|
+
if (!Array.isArray(local) || !Array.isArray(remote))
|
|
16363
|
+
return localSubsetOf(local, remote);
|
|
16364
|
+
const l = new Set(local.map(canonicalEffectTag));
|
|
16365
|
+
const r = new Set(remote.map(canonicalEffectTag));
|
|
16366
|
+
return l.size === r.size && [...l].every((tag) => r.has(tag));
|
|
16367
|
+
}
|
|
16333
16368
|
function diffFields(local, remote) {
|
|
16334
16369
|
const flatRemote = flattenDefinitionWrapper(remote);
|
|
16335
16370
|
const changed = [];
|
|
@@ -16342,7 +16377,8 @@ function diffFields(local, remote) {
|
|
|
16342
16377
|
continue;
|
|
16343
16378
|
const localVal = local[key];
|
|
16344
16379
|
const remoteVal = flatRemote[key];
|
|
16345
|
-
|
|
16380
|
+
const same = key === "risk_tags" ? effectTagsMatch(localVal, remoteVal) : localSubsetOf(localVal, remoteVal);
|
|
16381
|
+
if (!same) {
|
|
16346
16382
|
changed.push(key);
|
|
16347
16383
|
}
|
|
16348
16384
|
}
|
|
@@ -16614,6 +16650,8 @@ async function applyPrompt(api, op, def) {
|
|
|
16614
16650
|
createBody.description = def.body.description;
|
|
16615
16651
|
if (def.body.scope)
|
|
16616
16652
|
createBody.scope = def.body.scope;
|
|
16653
|
+
if (def.body.scope_entity_id)
|
|
16654
|
+
createBody.scope_entity_id = def.body.scope_entity_id;
|
|
16617
16655
|
const res = await api.post(promptPath, createBody);
|
|
16618
16656
|
const readBack = await api.get(`${promptPath}/${name}`);
|
|
16619
16657
|
const prodContent = readBack.production?.content;
|
|
@@ -16658,7 +16696,8 @@ async function applyPrompt(api, op, def) {
|
|
|
16658
16696
|
}
|
|
16659
16697
|
if (metadataFields.includes("scope")) {
|
|
16660
16698
|
await api.put(`${promptPath}/${name}/scope`, {
|
|
16661
|
-
scope: def.body.scope
|
|
16699
|
+
scope: def.body.scope,
|
|
16700
|
+
...def.body.scope_entity_id ? { scope_entity_id: def.body.scope_entity_id } : {}
|
|
16662
16701
|
});
|
|
16663
16702
|
}
|
|
16664
16703
|
if (Object.keys(metaBody).length > 0) {
|
|
@@ -28182,11 +28221,13 @@ async function checkHostRunners(ctx) {
|
|
|
28182
28221
|
detail: "none configured"
|
|
28183
28222
|
};
|
|
28184
28223
|
}
|
|
28185
|
-
const attached = names.filter((n) => presence[n]?.present).length;
|
|
28224
|
+
const attached = names.filter((n) => presence[n]?.present === true).length;
|
|
28225
|
+
const unknown = names.filter((n) => presence[n]?.present === null || presence[n]?.available === false).length;
|
|
28226
|
+
const detail = unknown ? `${names.length} configured, ${attached} attached, ${unknown} unknown (registry unreachable)` : `${names.length} configured, ${attached} attached`;
|
|
28186
28227
|
return {
|
|
28187
28228
|
name: "Host runners",
|
|
28188
|
-
status: "pass",
|
|
28189
|
-
detail
|
|
28229
|
+
status: unknown ? "warn" : "pass",
|
|
28230
|
+
detail,
|
|
28190
28231
|
remedy: `per-agent checkup: martha agents doctor <name>`
|
|
28191
28232
|
};
|
|
28192
28233
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -164,6 +164,10 @@ martha functions export [--format yaml|json] [--output FILE]
|
|
|
164
164
|
|
|
165
165
|
Function `auth` field is the most error-prone part — see the [Function authentication patterns](#function-authentication-patterns) section below.
|
|
166
166
|
|
|
167
|
+
**Call timeout (`tool` block, #1833 I5).** To let one call of a slow function run longer than the default, put `tool: { timeout: 60 }` (seconds, 1-900) at the top level of the `functions create|update -f` body. The server stores it in `definition.tool`. In chat the call's activity then gets `timeout` + 15 s (never under 30 s) instead of a fixed 30 s, and the handler bounds the call by `timeout`, with a 401 credential retry sharing the same deadline. A chat session keeps the bound its tool list had when it started, and calls are capped to fit it, so start a new session after raising `timeout`. Out-of-range values or unknown keys return **422**. A function with a `handler` (platform function) may not declare more than its handler's registry `timeout` (30 s unless the decorator sets another): create/update return **422** naming that bound, and a `timeout` on an unknown handler is a 422 too (MARTHA-626; only the `__system__` seed may exceed it, and older tenant rows above it are clamped at dispatch). `tool: {}` clears it. Platform functions get it from their decorator at seed time. `client_timeout_seconds` (1-86400) is stored but not read yet. `definitions apply` does not round-trip the block yet.
|
|
168
|
+
|
|
169
|
+
**Effect tags (`risk_tags`) are a closed vocabulary.** Allowed: `read_only`, `network`, `browser`, `untrusted_content`, `external_io`, `external_write`, `mutating`, `tenant_write`, `filesystem`, `host_execution`, `infra`, `destructive_write`, `payment`, `arbitrary_code`. Legacy spellings are mapped on write (`write`→`mutating`, `delete`→`destructive_write`, `host_exec`→`host_execution`, …), so a re-`get` can show a different tag than the file. Any other tag fails `create` / `update` / `definitions apply` with HTTP 422 `unknown_effect_tag`; the body's `suggestion` is the closest valid tag. Fix the file, don't retry. The live list is `martha policy show --json` → `risk_tag_vocabulary`. Full table: `docs/reference/effect-tags.md`.
|
|
170
|
+
|
|
167
171
|
### Workflows CRUD + Execution
|
|
168
172
|
|
|
169
173
|
```bash
|