martty 0.3.2-beta.3 → 0.3.2
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/lib/harnesses.js +55 -31
- package/package.json +8 -7
package/lib/harnesses.js
CHANGED
|
@@ -16,15 +16,18 @@ import {
|
|
|
16
16
|
installRegistryBinary,
|
|
17
17
|
managedBinaryPath,
|
|
18
18
|
normalizeAcpRegistry,
|
|
19
|
-
OPENMA_PI_ACP,
|
|
20
19
|
readAcpRegistrySnapshot,
|
|
21
20
|
} from './harness-registry.js'
|
|
21
|
+
import {
|
|
22
|
+
migrateLegacyAcpAgents,
|
|
23
|
+
readCustomAcpAgents,
|
|
24
|
+
removeCustomAcpAgent,
|
|
25
|
+
upsertCustomAcpAgent,
|
|
26
|
+
} from '@openma/common/acp-harnesses/custom-agents'
|
|
22
27
|
|
|
23
28
|
export { fetchAcpRegistry } from './harness-registry.js'
|
|
24
29
|
|
|
25
30
|
const HARNESS_ID = /^[a-z0-9][a-z0-9-]*$/
|
|
26
|
-
const PI_ACP_LATEST = OPENMA_PI_ACP
|
|
27
|
-
const PI_ACP_SPEC = /^(?:@openma\/)?pi-acp(?:@.+)?$/
|
|
28
31
|
const PI_ACP_ID = 'pi-acp'
|
|
29
32
|
const PI_ACP_LEGACY_LABEL = 'Pi (OpenMA)'
|
|
30
33
|
const ANSI = Object.freeze({ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m', cyan: '\x1b[36m', green: '\x1b[32m' })
|
|
@@ -368,12 +371,7 @@ function validateHarness(value) {
|
|
|
368
371
|
}
|
|
369
372
|
const isNpx = /^npx(?:\.(?:cmd|bat|exe))?$/i.test(path.win32.basename(value.command))
|
|
370
373
|
const normalizedArgs = isNpx
|
|
371
|
-
? [...args]
|
|
372
|
-
.filter((arg) => arg !== '--yes' && arg !== '--prefer-offline')
|
|
373
|
-
// A pinned pi-acp spec (any old `pi-acp@x` or `@openma/pi-acp@x` entry)
|
|
374
|
-
// always resolves `latest` at runtime instead — harness upgrades ship
|
|
375
|
-
// through npm, never through a Martty release.
|
|
376
|
-
.map((arg) => PI_ACP_SPEC.test(arg) ? PI_ACP_LATEST : arg)
|
|
374
|
+
? [...args].filter((arg) => arg !== '--yes' && arg !== '--prefer-offline')
|
|
377
375
|
: [...args]
|
|
378
376
|
const label = typeof value.label === 'string' && value.label.trim().length > 0
|
|
379
377
|
? value.label
|
|
@@ -389,9 +387,34 @@ function validateHarness(value) {
|
|
|
389
387
|
}
|
|
390
388
|
}
|
|
391
389
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
390
|
+
// Harness definitions live in <oma>/agents.json, the shared store from
|
|
391
|
+
// @openma/common — Backchat reads and writes the same file. Legacy rows
|
|
392
|
+
// still inside settings.json (and Backchat's config.toml overrides) keep
|
|
393
|
+
// reading through the shared module; the first shared write migrates
|
|
394
|
+
// harnesses[] into config.toml and strips the key so removals stick.
|
|
395
|
+
function settingsHome(settingsPath) {
|
|
396
|
+
return path.dirname(settingsPath)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function migrateStoredLabel(agent) {
|
|
400
|
+
// Configs saved when the pi harness was branded "Pi (OpenMA)" keep
|
|
401
|
+
// working; only the stale default display label migrates to the id.
|
|
402
|
+
return agent.id === PI_ACP_ID && agent.label === PI_ACP_LEGACY_LABEL
|
|
403
|
+
? { ...agent, label: PI_ACP_ID }
|
|
404
|
+
: agent
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function configuredHarnesses(settingsPath) {
|
|
408
|
+
// enabled=false is Backchat's disable flag: the definition stays stored
|
|
409
|
+
// but a disabled agent must not be selectable or launchable here.
|
|
410
|
+
return readCustomAcpAgents(settingsHome(settingsPath))
|
|
411
|
+
.filter((agent) => agent.enabled !== false)
|
|
412
|
+
.map(migrateStoredLabel)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function settingsWithoutHarnesses(settings) {
|
|
416
|
+
const { harnesses: _legacyHarnesses, ...rest } = settings
|
|
417
|
+
return rest
|
|
395
418
|
}
|
|
396
419
|
|
|
397
420
|
function withoutLegacyActive(settings) {
|
|
@@ -414,36 +437,37 @@ function persistedDefaultId(settings) {
|
|
|
414
437
|
|
|
415
438
|
export function upsertHarness(settingsPath, harness) {
|
|
416
439
|
const next = validateHarness(harness)
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
writeSettings(settingsPath,
|
|
440
|
+
// The shared write migrates legacy harnesses[] into config.toml and
|
|
441
|
+
// strips the key; read settings after it so a stale copy cannot race
|
|
442
|
+
// the migrated file back in.
|
|
443
|
+
upsertCustomAcpAgent(settingsHome(settingsPath), next)
|
|
444
|
+
const settings = withoutLegacyActive(readSettings(settingsPath))
|
|
445
|
+
writeSettings(settingsPath, settingsWithoutHarnesses(settings))
|
|
423
446
|
return next
|
|
424
447
|
}
|
|
425
448
|
|
|
426
449
|
export function setDefaultHarness(settingsPath, id) {
|
|
427
|
-
const
|
|
428
|
-
const harnesses = configuredHarnesses(settings)
|
|
450
|
+
const harnesses = configuredHarnesses(settingsPath)
|
|
429
451
|
if (!harnesses.some((harness) => harness.id === id)) {
|
|
430
452
|
throw new Error(`unknown harness ${JSON.stringify(id)}`)
|
|
431
453
|
}
|
|
432
|
-
|
|
454
|
+
const settings = withoutLegacyActive(readSettings(settingsPath))
|
|
455
|
+
migrateLegacyAcpAgents(settingsHome(settingsPath))
|
|
456
|
+
writeSettings(settingsPath, { ...settingsWithoutHarnesses(settings), defaultHarness: id })
|
|
433
457
|
}
|
|
434
458
|
|
|
435
459
|
export function savedHarnesses(settingsPath) {
|
|
436
|
-
return configuredHarnesses(
|
|
460
|
+
return configuredHarnesses(settingsPath)
|
|
437
461
|
}
|
|
438
462
|
|
|
439
463
|
export function removeHarnessConfiguration(settingsPath, expected) {
|
|
440
|
-
const
|
|
441
|
-
const harnesses = configuredHarnesses(settings)
|
|
442
|
-
const current = harnesses.find(({ id }) => id === expected.id)
|
|
464
|
+
const current = configuredHarnesses(settingsPath).find(({ id }) => id === expected.id)
|
|
443
465
|
if (JSON.stringify(current) !== JSON.stringify(expected)) throw new Error('Harness configuration changed; review removal again')
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
466
|
+
removeCustomAcpAgent(settingsHome(settingsPath), expected.id)
|
|
467
|
+
const settings = withoutLegacyActive(readSettings(settingsPath))
|
|
468
|
+
const rest = settingsWithoutHarnesses(settings)
|
|
469
|
+
if (rest.defaultHarness === expected.id) delete rest.defaultHarness
|
|
470
|
+
writeSettings(settingsPath, rest)
|
|
447
471
|
}
|
|
448
472
|
|
|
449
473
|
// Kept as a source-compatible alias for integrations compiled against 0.2.30.
|
|
@@ -454,7 +478,7 @@ export function selectedHarness(settingsPath) {
|
|
|
454
478
|
const settings = readSettings(settingsPath)
|
|
455
479
|
const id = persistedDefaultId(settings)
|
|
456
480
|
if (typeof id !== 'string') return undefined
|
|
457
|
-
return configuredHarnesses(
|
|
481
|
+
return configuredHarnesses(settingsPath).find((harness) => harness.id === id)
|
|
458
482
|
}
|
|
459
483
|
|
|
460
484
|
function executableFile(command) {
|
|
@@ -1010,7 +1034,7 @@ export function discoverHarnesses(settingsPath, options = {}) {
|
|
|
1010
1034
|
}
|
|
1011
1035
|
|
|
1012
1036
|
function discoverHarnessEntries(settingsPath, options, registryEntries) {
|
|
1013
|
-
const configured = configuredHarnesses(
|
|
1037
|
+
const configured = configuredHarnesses(settingsPath)
|
|
1014
1038
|
.map((harness) => ({ ...harness, source: 'configured' }))
|
|
1015
1039
|
const defaults = (options.defaults ?? []).map((entry) => ({
|
|
1016
1040
|
...validateHarness(entry),
|
|
@@ -1077,7 +1101,7 @@ function searchScore(entry, query = '') {
|
|
|
1077
1101
|
}
|
|
1078
1102
|
|
|
1079
1103
|
function findHarnessCandidates(settingsPath, options = {}, query = '') {
|
|
1080
|
-
const configured = configuredHarnesses(
|
|
1104
|
+
const configured = configuredHarnesses(settingsPath).map((entry) => ({
|
|
1081
1105
|
...entry,
|
|
1082
1106
|
source: 'configured',
|
|
1083
1107
|
status: 'Configured',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "martty",
|
|
3
|
-
"version": "0.3.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Terminal-native ACP client UI; Cordis client tree, any ACP agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -77,7 +77,8 @@
|
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
79
79
|
"@lobehub/icons-static-svg": "1.95.0",
|
|
80
|
-
"@openma/
|
|
80
|
+
"@openma/common": "^0.9.2",
|
|
81
|
+
"@openma/deepseek-harness-acp": "0.4.38",
|
|
81
82
|
"@resvg/resvg-js": "2.6.2",
|
|
82
83
|
"cross-spawn": "^7.0.6",
|
|
83
84
|
"node-downloader-helper": "2.1.11"
|
|
@@ -97,10 +98,10 @@
|
|
|
97
98
|
"agent-client-protocol"
|
|
98
99
|
],
|
|
99
100
|
"optionalDependencies": {
|
|
100
|
-
"@openma/martty-darwin-arm64": "0.3.2
|
|
101
|
-
"@openma/martty-darwin-x64": "0.3.2
|
|
102
|
-
"@openma/martty-linux-x64": "0.3.2
|
|
103
|
-
"@openma/martty-linux-arm64": "0.3.2
|
|
104
|
-
"@openma/martty-win32-x64": "0.3.2
|
|
101
|
+
"@openma/martty-darwin-arm64": "0.3.2",
|
|
102
|
+
"@openma/martty-darwin-x64": "0.3.2",
|
|
103
|
+
"@openma/martty-linux-x64": "0.3.2",
|
|
104
|
+
"@openma/martty-linux-arm64": "0.3.2",
|
|
105
|
+
"@openma/martty-win32-x64": "0.3.2"
|
|
105
106
|
}
|
|
106
107
|
}
|