oomi-ai 0.2.45 → 0.2.47
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/bin/oomi-ai.js +151 -8
- package/lib/personaApiClient.js +13 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/bin/oomi-ai.js
CHANGED
|
@@ -924,8 +924,98 @@ function collectManagedPersonaRefreshTargets({
|
|
|
924
924
|
|
|
925
925
|
return targets.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
926
926
|
}
|
|
927
|
-
|
|
928
|
-
|
|
927
|
+
|
|
928
|
+
function normalizeBackendPersonaRefreshRecord(rawPersona) {
|
|
929
|
+
if (!rawPersona || typeof rawPersona !== 'object') {
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
const slug = String(
|
|
934
|
+
rawPersona.slug ||
|
|
935
|
+
rawPersona.id ||
|
|
936
|
+
rawPersona.personaId ||
|
|
937
|
+
''
|
|
938
|
+
).trim();
|
|
939
|
+
if (!slug) {
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
return {
|
|
944
|
+
slug,
|
|
945
|
+
name: String(rawPersona.name || slug).trim() || slug,
|
|
946
|
+
description: String(rawPersona.description || rawPersona.summary || rawPersona.name || slug).trim() || slug,
|
|
947
|
+
templateVersion: String(rawPersona.promptTemplateVersion || 'v1').trim() || 'v1',
|
|
948
|
+
templateType: String(rawPersona.templateType || '').trim(),
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function resolveExistingWorkspacePathForSlug(slug, workspaceRoot = defaultPersonaWorkspaceRoot()) {
|
|
953
|
+
for (const root of listPersonaWorkspaceRoots(workspaceRoot)) {
|
|
954
|
+
const workspacePath = resolvePersonaWorkspacePath({
|
|
955
|
+
workspaceRoot: root,
|
|
956
|
+
slug,
|
|
957
|
+
});
|
|
958
|
+
if (fs.existsSync(workspacePath)) {
|
|
959
|
+
return workspacePath;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return '';
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
async function discoverBackendLinkedPersonaRefreshTargets({
|
|
966
|
+
client,
|
|
967
|
+
workspaceRoot = defaultPersonaWorkspaceRoot(),
|
|
968
|
+
existingTargets = [],
|
|
969
|
+
logger = null,
|
|
970
|
+
} = {}) {
|
|
971
|
+
if (!client || typeof client.listPersonas !== 'function') {
|
|
972
|
+
return [];
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
const targetsBySlug = new Map(
|
|
976
|
+
Array.isArray(existingTargets)
|
|
977
|
+
? existingTargets.map((target) => [String(target?.slug || '').trim(), target]).filter(([slug]) => slug)
|
|
978
|
+
: [],
|
|
979
|
+
);
|
|
980
|
+
|
|
981
|
+
const payload = await client.listPersonas();
|
|
982
|
+
const backendPersonas = Array.isArray(payload?.personas) ? payload.personas : [];
|
|
983
|
+
const discoveredTargets = [];
|
|
984
|
+
|
|
985
|
+
for (const rawPersona of backendPersonas) {
|
|
986
|
+
const backendPersona = normalizeBackendPersonaRefreshRecord(rawPersona);
|
|
987
|
+
if (!backendPersona || targetsBySlug.has(backendPersona.slug)) {
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
const workspacePath = resolveExistingWorkspacePathForSlug(backendPersona.slug, workspaceRoot);
|
|
991
|
+
if (!workspacePath) {
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
const state = readPersonaRuntimeState(workspacePath);
|
|
995
|
+
const target = {
|
|
996
|
+
slug: backendPersona.slug,
|
|
997
|
+
workspacePath,
|
|
998
|
+
state: {
|
|
999
|
+
...state,
|
|
1000
|
+
slug: backendPersona.slug,
|
|
1001
|
+
name: backendPersona.name,
|
|
1002
|
+
description: backendPersona.description,
|
|
1003
|
+
templateVersion: backendPersona.templateVersion,
|
|
1004
|
+
},
|
|
1005
|
+
processRunning: false,
|
|
1006
|
+
};
|
|
1007
|
+
discoveredTargets.push(target);
|
|
1008
|
+
targetsBySlug.set(backendPersona.slug, target);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
if (discoveredTargets.length > 0) {
|
|
1012
|
+
logger?.(`Added ${discoveredTargets.length} backend-linked persona runtime target${discoveredTargets.length === 1 ? '' : 's'} from workspace discovery.`);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
return discoveredTargets;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
async function findExistingManagedPersona(client, slug) {
|
|
929
1019
|
try {
|
|
930
1020
|
return await client.getPersona({ slug });
|
|
931
1021
|
} catch (error) {
|
|
@@ -1566,13 +1656,16 @@ async function handlePersonaDeleteCommand(slug, flags = {}) {
|
|
|
1566
1656
|
printStructuredResult(result, isTruthyFlag(flags.json));
|
|
1567
1657
|
}
|
|
1568
1658
|
|
|
1569
|
-
async function restartManagedPersonaRefreshTargets(flags = {}) {
|
|
1659
|
+
async function restartManagedPersonaRefreshTargets(flags = {}, options = {}) {
|
|
1570
1660
|
const workspaceRoot = resolvePersonaWorkspaceRoot(flags);
|
|
1571
|
-
const
|
|
1661
|
+
const localTargets = collectManagedPersonaRefreshTargets({
|
|
1572
1662
|
workspaceRoot,
|
|
1573
1663
|
includeStopped: isTruthyFlag(flags['include-stopped']),
|
|
1574
1664
|
});
|
|
1665
|
+
const targetsBySlug = new Map(localTargets.map((target) => [target.slug, target]));
|
|
1666
|
+
const targets = [...localTargets];
|
|
1575
1667
|
const results = [];
|
|
1668
|
+
const logger = options.logger || null;
|
|
1576
1669
|
|
|
1577
1670
|
let client = null;
|
|
1578
1671
|
let registrationError = '';
|
|
@@ -1580,10 +1673,35 @@ async function restartManagedPersonaRefreshTargets(flags = {}) {
|
|
|
1580
1673
|
client = createCliPersonaApiClient(flags);
|
|
1581
1674
|
} catch (error) {
|
|
1582
1675
|
registrationError = error instanceof Error ? error.message : String(error);
|
|
1676
|
+
logger?.(`Persona backend registration unavailable: ${registrationError}`);
|
|
1583
1677
|
}
|
|
1584
1678
|
|
|
1679
|
+
if (client) {
|
|
1680
|
+
try {
|
|
1681
|
+
const backendTargets = await discoverBackendLinkedPersonaRefreshTargets({
|
|
1682
|
+
client,
|
|
1683
|
+
workspaceRoot,
|
|
1684
|
+
existingTargets: targets,
|
|
1685
|
+
logger,
|
|
1686
|
+
});
|
|
1687
|
+
for (const target of backendTargets) {
|
|
1688
|
+
targetsBySlug.set(target.slug, target);
|
|
1689
|
+
targets.push(target);
|
|
1690
|
+
}
|
|
1691
|
+
} catch (error) {
|
|
1692
|
+
logger?.(`Backend persona discovery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
logger?.(
|
|
1697
|
+
`Discovered ${targets.length} managed persona runtime${targets.length == 1 ? '' : 's'} to refresh.`,
|
|
1698
|
+
);
|
|
1699
|
+
|
|
1585
1700
|
for (const target of targets) {
|
|
1586
1701
|
const state = target.state && typeof target.state === 'object' ? target.state : {};
|
|
1702
|
+
logger?.(
|
|
1703
|
+
`Refreshing persona ${target.slug} (previous port: ${String(state.localPort || 'unknown')}).`,
|
|
1704
|
+
);
|
|
1587
1705
|
const launchResult = await launchManagedPersonaRuntime({
|
|
1588
1706
|
slug: target.slug,
|
|
1589
1707
|
name: String(state.name || target.slug).trim() || target.slug,
|
|
@@ -1600,6 +1718,7 @@ async function restartManagedPersonaRefreshTargets(flags = {}) {
|
|
|
1600
1718
|
let registration = null;
|
|
1601
1719
|
if (client) {
|
|
1602
1720
|
try {
|
|
1721
|
+
logger?.(`Re-registering runtime for ${launchResult.slug} at ${launchResult.runtime.endpoint}.`);
|
|
1603
1722
|
registration = await client.registerRuntime({
|
|
1604
1723
|
slug: launchResult.slug,
|
|
1605
1724
|
endpoint: launchResult.runtime.endpoint,
|
|
@@ -1613,9 +1732,14 @@ async function restartManagedPersonaRefreshTargets(flags = {}) {
|
|
|
1613
1732
|
ok: false,
|
|
1614
1733
|
error: error instanceof Error ? error.message : String(error),
|
|
1615
1734
|
};
|
|
1735
|
+
logger?.(`Runtime registration failed for ${launchResult.slug}: ${registration.error}`);
|
|
1616
1736
|
}
|
|
1617
1737
|
}
|
|
1618
1738
|
|
|
1739
|
+
logger?.(
|
|
1740
|
+
`Persona ${launchResult.slug} refreshed on port ${launchResult.runtime.localPort} (${launchResult.runtime.endpoint}).`,
|
|
1741
|
+
);
|
|
1742
|
+
|
|
1619
1743
|
results.push({
|
|
1620
1744
|
slug: launchResult.slug,
|
|
1621
1745
|
workspacePath: launchResult.workspacePath,
|
|
@@ -1634,10 +1758,12 @@ async function restartManagedPersonaRefreshTargets(flags = {}) {
|
|
|
1634
1758
|
};
|
|
1635
1759
|
}
|
|
1636
1760
|
|
|
1637
|
-
async function refreshBridgeForUpdate(flags = {}) {
|
|
1761
|
+
async function refreshBridgeForUpdate(flags = {}, options = {}) {
|
|
1762
|
+
const logger = options.logger || null;
|
|
1638
1763
|
if (process.platform === 'darwin') {
|
|
1639
1764
|
const launchdStatus = readBridgeLaunchdStatus();
|
|
1640
1765
|
if (launchdStatus.installed) {
|
|
1766
|
+
logger?.(`Restarting launchd-managed bridge ${launchdStatus.target}.`);
|
|
1641
1767
|
await stopBridgeLaunchdService();
|
|
1642
1768
|
startBridgeLaunchdService();
|
|
1643
1769
|
incrementBridgeMetric('bridge_restart_count');
|
|
@@ -1651,12 +1777,14 @@ async function refreshBridgeForUpdate(flags = {}) {
|
|
|
1651
1777
|
|
|
1652
1778
|
const running = findRunningBridgeProcess();
|
|
1653
1779
|
if (!running) {
|
|
1780
|
+
logger?.('No bridge process is currently running; skipping bridge restart.');
|
|
1654
1781
|
return {
|
|
1655
1782
|
restarted: false,
|
|
1656
1783
|
mode: 'process',
|
|
1657
1784
|
};
|
|
1658
1785
|
}
|
|
1659
1786
|
|
|
1787
|
+
logger?.(`Restarting bridge process ${running.pid}.`);
|
|
1660
1788
|
const stopResult = await stopBridgeProcesses();
|
|
1661
1789
|
if (Array.isArray(stopResult.stillAlive) && stopResult.stillAlive.length > 0) {
|
|
1662
1790
|
throw new Error(`Failed to stop bridge processes: ${stopResult.stillAlive.join(', ')}`);
|
|
@@ -1673,19 +1801,31 @@ async function refreshBridgeForUpdate(flags = {}) {
|
|
|
1673
1801
|
}
|
|
1674
1802
|
|
|
1675
1803
|
async function handleOpenclawRefreshCommand(flags = {}) {
|
|
1804
|
+
const jsonOutput = isTruthyFlag(flags.json);
|
|
1805
|
+
const logProgress = jsonOutput ? null : (message) => console.log(`[refresh] ${message}`);
|
|
1676
1806
|
const currentVersion = currentPackageVersion();
|
|
1677
1807
|
let latestVersion = '';
|
|
1678
1808
|
if (!isTruthyFlag(flags['skip-version-check'])) {
|
|
1809
|
+
logProgress?.(`Checking npm for the latest oomi-ai version (installed: ${currentVersion || 'unknown'}).`);
|
|
1679
1810
|
latestVersion = await fetchLatestPublishedVersion('oomi-ai');
|
|
1680
1811
|
if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {
|
|
1681
1812
|
throw new Error(
|
|
1682
1813
|
`Installed oomi-ai ${currentVersion} is behind npm ${latestVersion}. Update first, then rerun: oomi openclaw refresh`
|
|
1683
1814
|
);
|
|
1684
1815
|
}
|
|
1816
|
+
if (latestVersion) {
|
|
1817
|
+
logProgress?.(`Latest published version is ${latestVersion}.`);
|
|
1818
|
+
}
|
|
1685
1819
|
}
|
|
1686
1820
|
|
|
1687
|
-
|
|
1688
|
-
const
|
|
1821
|
+
logProgress?.('Refreshing managed persona runtimes.');
|
|
1822
|
+
const personaRefresh = await restartManagedPersonaRefreshTargets(flags, {
|
|
1823
|
+
logger: logProgress,
|
|
1824
|
+
});
|
|
1825
|
+
logProgress?.('Refreshing bridge process.');
|
|
1826
|
+
const bridgeRefresh = await refreshBridgeForUpdate(flags, {
|
|
1827
|
+
logger: logProgress,
|
|
1828
|
+
});
|
|
1689
1829
|
const payload = {
|
|
1690
1830
|
ok: true,
|
|
1691
1831
|
currentVersion,
|
|
@@ -1699,7 +1839,7 @@ async function handleOpenclawRefreshCommand(flags = {}) {
|
|
|
1699
1839
|
bridge: bridgeRefresh,
|
|
1700
1840
|
};
|
|
1701
1841
|
|
|
1702
|
-
if (
|
|
1842
|
+
if (jsonOutput) {
|
|
1703
1843
|
console.log(JSON.stringify(payload, null, 2));
|
|
1704
1844
|
return;
|
|
1705
1845
|
}
|
|
@@ -5827,5 +5967,8 @@ export {
|
|
|
5827
5967
|
isBridgeWorkerCommand,
|
|
5828
5968
|
parsePositiveInteger,
|
|
5829
5969
|
collectManagedPersonaRefreshTargets,
|
|
5970
|
+
discoverBackendLinkedPersonaRefreshTargets,
|
|
5971
|
+
normalizeBackendPersonaRefreshRecord,
|
|
5830
5972
|
resolvePersonaRuntimeInput,
|
|
5973
|
+
resolveExistingWorkspacePathForSlug,
|
|
5831
5974
|
};
|
package/lib/personaApiClient.js
CHANGED
|
@@ -100,10 +100,19 @@ export function createPersonaApiClient({
|
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
return {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
return {
|
|
104
|
+
listPersonas() {
|
|
105
|
+
return getJson({
|
|
106
|
+
fetchImpl,
|
|
107
|
+
backendUrl: resolvedBackendUrl,
|
|
108
|
+
deviceToken: resolvedDeviceToken,
|
|
109
|
+
path: '/v1/personas',
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
getPersona({
|
|
114
|
+
slug,
|
|
115
|
+
}) {
|
|
107
116
|
const safeSlug = trimString(slug);
|
|
108
117
|
if (!safeSlug) {
|
|
109
118
|
throw new Error('Persona slug is required.');
|
package/openclaw.plugin.json
CHANGED