@rynx-ai/daemon 0.1.10 → 0.1.11-beta.10
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/bundled-plugins/.rynx-plugin/marketplace.json +10 -0
- package/bundled-plugins/plugins/lark/.rynx-plugin/plugin.json +25 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.d.ts +48 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.js +56 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-mirror.d.ts +85 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-mirror.js +333 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-watcher.d.ts +109 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-watcher.js +347 -0
- package/bundled-plugins/plugins/lark/dist/host-adapters.d.ts +95 -0
- package/bundled-plugins/plugins/lark/dist/host-adapters.js +506 -0
- package/bundled-plugins/plugins/lark/dist/index.d.ts +7 -0
- package/bundled-plugins/plugins/lark/dist/index.js +7 -0
- package/bundled-plugins/plugins/lark/dist/lark-card-stream.d.ts +363 -0
- package/bundled-plugins/plugins/lark/dist/lark-card-stream.js +1335 -0
- package/bundled-plugins/plugins/lark/dist/lark-config-store.d.ts +30 -0
- package/bundled-plugins/plugins/lark/dist/lark-config-store.js +135 -0
- package/bundled-plugins/plugins/lark/dist/lark-content.d.ts +30 -0
- package/bundled-plugins/plugins/lark/dist/lark-content.js +138 -0
- package/bundled-plugins/plugins/lark/dist/lark-conversation-directory.d.ts +65 -0
- package/bundled-plugins/plugins/lark/dist/lark-conversation-directory.js +106 -0
- package/bundled-plugins/plugins/lark/dist/lark-diff-card.d.ts +25 -0
- package/bundled-plugins/plugins/lark/dist/lark-diff-card.js +58 -0
- package/bundled-plugins/plugins/lark/dist/lark-fork-transcript.d.ts +16 -0
- package/bundled-plugins/plugins/lark/dist/lark-fork-transcript.js +141 -0
- package/bundled-plugins/plugins/lark/dist/lark-resume-card.d.ts +31 -0
- package/bundled-plugins/plugins/lark/dist/lark-resume-card.js +105 -0
- package/bundled-plugins/plugins/lark/dist/lark-runtime-state-store.d.ts +18 -0
- package/bundled-plugins/plugins/lark/dist/lark-runtime-state-store.js +95 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/client.d.ts +8 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/client.js +32 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/index.d.ts +1 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/index.js +1 -0
- package/bundled-plugins/plugins/lark/dist/lark-sender.d.ts +114 -0
- package/bundled-plugins/plugins/lark/dist/lark-sender.js +323 -0
- package/bundled-plugins/plugins/lark/dist/lark-session-store.d.ts +13 -0
- package/bundled-plugins/plugins/lark/dist/lark-session-store.js +14 -0
- package/bundled-plugins/plugins/lark/dist/lark-settings-card.d.ts +55 -0
- package/bundled-plugins/plugins/lark/dist/lark-settings-card.js +158 -0
- package/bundled-plugins/plugins/lark/dist/lark-setup.d.ts +39 -0
- package/bundled-plugins/plugins/lark/dist/lark-setup.js +103 -0
- package/bundled-plugins/plugins/lark/dist/lark.d.ts +507 -0
- package/bundled-plugins/plugins/lark/dist/lark.js +1975 -0
- package/bundled-plugins/plugins/lark/dist/runtime.d.ts +13 -0
- package/bundled-plugins/plugins/lark/dist/runtime.js +131328 -0
- package/bundled-plugins/plugins/lark/dist/settings.d.ts +7 -0
- package/bundled-plugins/plugins/lark/dist/settings.js +126971 -0
- package/bundled-plugins/plugins/lark/package.json +57 -0
- package/bundled-plugins/plugins/lark/ui/assets/index-CGUVAMsv.css +1 -0
- package/bundled-plugins/plugins/lark/ui/assets/index-D8Amoe6a.js +201 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/index.html +13 -0
- package/dist/agent-file.js +0 -1
- package/dist/browser-artifact-management.d.ts +4 -1
- package/dist/browser-artifact-management.js +18 -10
- package/dist/browser-artifacts.d.ts +1 -0
- package/dist/browser-artifacts.js +1 -0
- package/dist/bundled-plugins.d.ts +15 -0
- package/dist/bundled-plugins.js +134 -0
- package/dist/chrome-for-testing-runtime.d.ts +27 -0
- package/dist/chrome-for-testing-runtime.js +193 -0
- package/dist/chrome-for-testing-store.d.ts +2 -0
- package/dist/chrome-for-testing-store.js +9 -0
- package/dist/control-deps.d.ts +6 -2
- package/dist/control-deps.js +88 -82
- package/dist/daemon-server.d.ts +7 -1
- package/dist/daemon-server.js +310 -87
- package/dist/db.js +181 -124
- package/dist/entry-path.d.ts +3 -0
- package/dist/entry-path.js +12 -0
- package/dist/index-daemon.js +3 -66
- package/dist/lifecycle.d.ts +12 -0
- package/dist/lifecycle.js +16 -0
- package/dist/maintenance-lease.d.ts +39 -0
- package/dist/maintenance-lease.js +250 -0
- package/dist/migrations/cleanup-legacy-sessions.d.ts +1 -1
- package/dist/migrations/cleanup-legacy-sessions.js +33 -15
- package/dist/official-plugins.d.ts +2 -0
- package/dist/official-plugins.js +2 -0
- package/dist/plugin-cli.d.ts +1 -3
- package/dist/plugin-cli.js +56 -45
- package/dist/plugin-host-leases.d.ts +4 -0
- package/dist/plugin-host-leases.js +7 -0
- package/dist/plugin-host-rpc.d.ts +73 -6
- package/dist/plugin-host-rpc.js +354 -81
- package/dist/plugin-installer.d.ts +24 -55
- package/dist/plugin-installer.js +258 -412
- package/dist/plugin-management-service.d.ts +30 -23
- package/dist/plugin-management-service.js +288 -105
- package/dist/plugin-marketplace.d.ts +35 -0
- package/dist/plugin-marketplace.js +299 -0
- package/dist/plugin-package.d.ts +22 -24
- package/dist/plugin-package.js +520 -571
- package/dist/plugin-skill-context.d.ts +4 -0
- package/dist/plugin-skill-context.js +35 -0
- package/dist/plugin-store.d.ts +36 -37
- package/dist/plugin-store.js +138 -92
- package/dist/plugin-supervisor.d.ts +50 -125
- package/dist/plugin-supervisor.js +678 -1030
- package/dist/pm2.d.ts +11 -2
- package/dist/pm2.js +130 -28
- package/dist/process.d.ts +12 -0
- package/dist/process.js +91 -0
- package/dist/runtime-project-store.d.ts +9 -0
- package/dist/runtime-project-store.js +83 -0
- package/dist/session-fallback-workspace.d.ts +22 -0
- package/dist/session-fallback-workspace.js +120 -0
- package/dist/session-fork-store.d.ts +41 -0
- package/dist/session-fork-store.js +288 -0
- package/dist/session-launch-operations.d.ts +23 -2
- package/dist/session-launch-operations.js +48 -7
- package/dist/session-meta-store.d.ts +12 -9
- package/dist/session-meta-store.js +50 -49
- package/dist/session-portal-grant-store.d.ts +29 -0
- package/dist/session-portal-grant-store.js +84 -0
- package/dist/setup-service.d.ts +21 -0
- package/dist/setup-service.js +39 -0
- package/dist/skills-catalog.d.ts +11 -2
- package/dist/skills-catalog.js +307 -7
- package/dist/system-dependencies.d.ts +26 -0
- package/dist/system-dependencies.js +149 -0
- package/package.json +36 -20
- package/dist/browser-cli-args.d.ts +0 -20
- package/dist/browser-cli-args.js +0 -100
- package/dist/channel-store.d.ts +0 -22
- package/dist/channel-store.js +0 -65
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -732
- package/dist/control-client.d.ts +0 -122
- package/dist/control-client.js +0 -855
- package/dist/control-endpoint.d.ts +0 -14
- package/dist/control-endpoint.js +0 -124
- package/dist/desktop-browser-host-client.d.ts +0 -35
- package/dist/desktop-browser-host-client.js +0 -415
- package/dist/instance-store.d.ts +0 -38
- package/dist/instance-store.js +0 -85
- package/dist/plugin-install-restart.d.ts +0 -13
- package/dist/plugin-install-restart.js +0 -24
- package/dist/plugin-runtime-control.d.ts +0 -2
- package/dist/plugin-runtime-control.js +0 -37
- package/dist/registry.d.ts +0 -10
- package/dist/registry.js +0 -52
- package/dist/setup.d.ts +0 -20
- package/dist/setup.js +0 -374
- package/dist/update.d.ts +0 -25
- package/dist/update.js +0 -133
package/dist/instance-store.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `instances` table CRUD — a runnable binding of a channel to an agent (1:1 with
|
|
3
|
-
* a channel, enforced by a UNIQUE channel_id). The daemon mounts enabled
|
|
4
|
-
* instances; each resolves to its channel's type + options plus the bound agent.
|
|
5
|
-
*/
|
|
6
|
-
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { db } from "./db.js";
|
|
8
|
-
function parseOptions(raw) {
|
|
9
|
-
if (!raw)
|
|
10
|
-
return undefined;
|
|
11
|
-
try {
|
|
12
|
-
const parsed = JSON.parse(raw);
|
|
13
|
-
return parsed && typeof parsed === "object" ? parsed : undefined;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
const JOIN_SELECT = `
|
|
20
|
-
SELECT i.id, i.channel_id, i.agent, i.enabled,
|
|
21
|
-
c.name AS channel_name, c.type AS type, c.options AS options
|
|
22
|
-
FROM instances i JOIN channels c ON c.id = i.channel_id`;
|
|
23
|
-
function toView(row) {
|
|
24
|
-
return {
|
|
25
|
-
id: row.id,
|
|
26
|
-
channelId: row.channel_id,
|
|
27
|
-
channelName: row.channel_name,
|
|
28
|
-
type: row.type,
|
|
29
|
-
agent: row.agent ?? undefined,
|
|
30
|
-
enabled: row.enabled !== 0,
|
|
31
|
-
options: parseOptions(row.options),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
export function listInstances() {
|
|
35
|
-
const rows = db().prepare(`${JOIN_SELECT} ORDER BY c.name`).all();
|
|
36
|
-
return rows.map(toView);
|
|
37
|
-
}
|
|
38
|
-
export function getInstance(id) {
|
|
39
|
-
const row = db().prepare(`${JOIN_SELECT} WHERE i.id = ?`).get(id);
|
|
40
|
-
return row ? toView(row) : undefined;
|
|
41
|
-
}
|
|
42
|
-
/** Mountable descriptors for every enabled instance (joined with its channel). */
|
|
43
|
-
export function listEnabledDescriptors() {
|
|
44
|
-
const rows = db().prepare(`${JOIN_SELECT} WHERE i.enabled = 1`).all();
|
|
45
|
-
return rows.map((row) => ({
|
|
46
|
-
instanceId: row.id,
|
|
47
|
-
type: row.type,
|
|
48
|
-
options: parseOptions(row.options),
|
|
49
|
-
agent: row.agent ?? undefined,
|
|
50
|
-
}));
|
|
51
|
-
}
|
|
52
|
-
/** Bind a channel to an agent. Throws if the channel already has an instance. */
|
|
53
|
-
export function createInstance(input) {
|
|
54
|
-
const id = randomUUID();
|
|
55
|
-
const now = new Date().toISOString();
|
|
56
|
-
db()
|
|
57
|
-
.prepare(`INSERT INTO instances (id, channel_id, agent, enabled, created_at, updated_at)
|
|
58
|
-
VALUES (@id, @channelId, @agent, @enabled, @now, @now)`)
|
|
59
|
-
.run({
|
|
60
|
-
id,
|
|
61
|
-
channelId: input.channelId,
|
|
62
|
-
agent: input.agent ?? null,
|
|
63
|
-
enabled: input.enabled === false ? 0 : 1,
|
|
64
|
-
now,
|
|
65
|
-
});
|
|
66
|
-
return { id, channelId: input.channelId, agent: input.agent, enabled: input.enabled !== false };
|
|
67
|
-
}
|
|
68
|
-
export function setInstanceAgent(id, agent) {
|
|
69
|
-
db()
|
|
70
|
-
.prepare("UPDATE instances SET agent = ?, updated_at = ? WHERE id = ?")
|
|
71
|
-
.run(agent ?? null, new Date().toISOString(), id);
|
|
72
|
-
}
|
|
73
|
-
export function setInstanceEnabled(id, enabled) {
|
|
74
|
-
db()
|
|
75
|
-
.prepare("UPDATE instances SET enabled = ?, updated_at = ? WHERE id = ?")
|
|
76
|
-
.run(enabled ? 1 : 0, new Date().toISOString(), id);
|
|
77
|
-
}
|
|
78
|
-
export function removeInstance(id) {
|
|
79
|
-
db().prepare("DELETE FROM instances WHERE id = ?").run(id);
|
|
80
|
-
}
|
|
81
|
-
/** The instance bound to a channel, if any (1:1). */
|
|
82
|
-
export function getInstanceByChannel(channelId) {
|
|
83
|
-
const row = db().prepare(`${JOIN_SELECT} WHERE i.channel_id = ?`).get(channelId);
|
|
84
|
-
return row ? toView(row) : undefined;
|
|
85
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export type PluginInstallRestartResult = "restarted" | "declined" | "not-running";
|
|
2
|
-
export interface PluginInstallRestartOptions {
|
|
3
|
-
restart: boolean;
|
|
4
|
-
interactive: boolean;
|
|
5
|
-
}
|
|
6
|
-
export interface PluginInstallRestartDeps {
|
|
7
|
-
isDaemonOnline(): boolean;
|
|
8
|
-
confirmRestart(): Promise<boolean>;
|
|
9
|
-
restartDaemon(): number;
|
|
10
|
-
log(message: string): void;
|
|
11
|
-
}
|
|
12
|
-
/** Apply an installed plugin immediately without unexpectedly starting a stopped daemon. */
|
|
13
|
-
export declare function restartAfterPluginInstall(options: PluginInstallRestartOptions, deps: PluginInstallRestartDeps): Promise<PluginInstallRestartResult>;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/** Apply an installed plugin immediately without unexpectedly starting a stopped daemon. */
|
|
2
|
-
export async function restartAfterPluginInstall(options, deps) {
|
|
3
|
-
if (!options.interactive && !options.restart) {
|
|
4
|
-
deps.log("Rynx was not restarted in non-interactive mode. Pass `--restart` to apply the plugin immediately.");
|
|
5
|
-
return "declined";
|
|
6
|
-
}
|
|
7
|
-
if (!deps.isDaemonOnline()) {
|
|
8
|
-
deps.log("Rynx is not running under PM2; the plugin will load when its owning service next starts or restarts.");
|
|
9
|
-
return "not-running";
|
|
10
|
-
}
|
|
11
|
-
const shouldRestart = options.restart
|
|
12
|
-
? true
|
|
13
|
-
: options.interactive
|
|
14
|
-
? await deps.confirmRestart()
|
|
15
|
-
: false;
|
|
16
|
-
if (!shouldRestart) {
|
|
17
|
-
deps.log("Rynx restart skipped. Run `rynx restart` when you are ready to apply the plugin.");
|
|
18
|
-
return "declined";
|
|
19
|
-
}
|
|
20
|
-
if (deps.restartDaemon() !== 0) {
|
|
21
|
-
throw new Error("Plugin installed, but Rynx failed to restart. Run `rynx restart` manually.");
|
|
22
|
-
}
|
|
23
|
-
return "restarted";
|
|
24
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { ensureDaemonControlEndpoint } from "./control-endpoint.js";
|
|
2
|
-
const RELOAD_TIMEOUT_MS = 30_000;
|
|
3
|
-
export async function reloadResidentPluginRuntime(pluginId) {
|
|
4
|
-
return requestResidentPluginRuntime(pluginId, "reload");
|
|
5
|
-
}
|
|
6
|
-
export async function ensureResidentPluginRuntime(pluginId) {
|
|
7
|
-
return requestResidentPluginRuntime(pluginId, "ensure");
|
|
8
|
-
}
|
|
9
|
-
async function requestResidentPluginRuntime(pluginId, operation) {
|
|
10
|
-
if (!/^[a-z][a-z0-9-]{0,62}$/.test(pluginId))
|
|
11
|
-
throw new Error("invalid plugin id");
|
|
12
|
-
const endpoint = await ensureDaemonControlEndpoint();
|
|
13
|
-
const response = await fetch(`${endpoint.origin}/api/internal/plugin-runtimes/${encodeURIComponent(pluginId)}/${operation}`, {
|
|
14
|
-
method: "POST",
|
|
15
|
-
headers: { "x-rynx-management-token": endpoint.managementToken },
|
|
16
|
-
signal: AbortSignal.timeout(RELOAD_TIMEOUT_MS),
|
|
17
|
-
});
|
|
18
|
-
const body = await response.text();
|
|
19
|
-
if (!response.ok) {
|
|
20
|
-
throw new Error(readError(body) || `plugin runtime refresh failed (${response.status})`);
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(body);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
throw new Error("daemon returned an invalid plugin runtime refresh response");
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function readError(body) {
|
|
30
|
-
try {
|
|
31
|
-
const parsed = JSON.parse(body);
|
|
32
|
-
return typeof parsed.error === "string" ? parsed.error : undefined;
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return body.trim().slice(0, 2_000) || undefined;
|
|
36
|
-
}
|
|
37
|
-
}
|
package/dist/registry.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type ChannelInstanceDescriptor, type ChannelTypeDescriptor } from "@rynx-ai/core";
|
|
2
|
-
import type { PluginSupervisor } from "./plugin-supervisor.js";
|
|
3
|
-
/** Directory plugin packages and staging data live under. */
|
|
4
|
-
export declare function pluginsDir(): string;
|
|
5
|
-
export declare function listChannelTypes(): ChannelTypeDescriptor[];
|
|
6
|
-
export declare function getChannelType(type: string): ChannelTypeDescriptor | undefined;
|
|
7
|
-
/** Rebuild the catalog from static manifests projected by the supervisor. */
|
|
8
|
-
export declare function loadPlugins(supervisor: PluginSupervisor, warn?: (message: string) => void): Promise<void>;
|
|
9
|
-
/** Join enabled channel instances to their remote runner-backed factories. */
|
|
10
|
-
export declare function resolveChannelInstances(warn?: (message: string) => void): Promise<ChannelInstanceDescriptor[]>;
|
package/dist/registry.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static plugin catalog.
|
|
3
|
-
*
|
|
4
|
-
* Installation records already contain validated pure-data manifests. This
|
|
5
|
-
* module joins their chat-channel declarations to host-side remote lifecycle
|
|
6
|
-
* adapters supplied by PluginSupervisor. It never imports an installed plugin
|
|
7
|
-
* entry point.
|
|
8
|
-
*/
|
|
9
|
-
import { join } from "node:path";
|
|
10
|
-
import { rynxHome, } from "@rynx-ai/core";
|
|
11
|
-
import { listEnabledDescriptors } from "./instance-store.js";
|
|
12
|
-
/** Directory plugin packages and staging data live under. */
|
|
13
|
-
export function pluginsDir() {
|
|
14
|
-
return process.env.RYNX_PLUGINS_DIR?.trim() || join(rynxHome(), "plugins");
|
|
15
|
-
}
|
|
16
|
-
const catalog = new Map();
|
|
17
|
-
export function listChannelTypes() {
|
|
18
|
-
return [...catalog.values()];
|
|
19
|
-
}
|
|
20
|
-
export function getChannelType(type) {
|
|
21
|
-
return catalog.get(type);
|
|
22
|
-
}
|
|
23
|
-
/** Rebuild the catalog from static manifests projected by the supervisor. */
|
|
24
|
-
export async function loadPlugins(supervisor, warn = () => { }) {
|
|
25
|
-
catalog.clear();
|
|
26
|
-
for (const channel of supervisor.createChannelTypeDescriptors()) {
|
|
27
|
-
if (catalog.has(channel.type)) {
|
|
28
|
-
warn(`chat channel type "${channel.type}" is declared by more than one plugin; later declaration ignored`);
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
catalog.set(channel.type, channel);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/** Join enabled channel instances to their remote runner-backed factories. */
|
|
35
|
-
export async function resolveChannelInstances(warn = () => { }) {
|
|
36
|
-
const instances = [];
|
|
37
|
-
for (const descriptor of listEnabledDescriptors()) {
|
|
38
|
-
const channel = catalog.get(descriptor.type);
|
|
39
|
-
if (!channel) {
|
|
40
|
-
warn(`unknown chat channel type "${descriptor.type}" (instance "${descriptor.instanceId}") — no enabled plugin declares it; skipped`);
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
instances.push({
|
|
44
|
-
instanceId: descriptor.instanceId,
|
|
45
|
-
type: descriptor.type,
|
|
46
|
-
factory: channel.factory,
|
|
47
|
-
options: descriptor.options,
|
|
48
|
-
agent: descriptor.agent,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return instances;
|
|
52
|
-
}
|
package/dist/setup.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
type ControlListenMode = "loopback" | "host";
|
|
2
|
-
type ManagedBrowserSetupPlan = {
|
|
3
|
-
kind: "ready";
|
|
4
|
-
} | {
|
|
5
|
-
kind: "unsupported";
|
|
6
|
-
} | {
|
|
7
|
-
kind: "offer";
|
|
8
|
-
installByDefault: boolean;
|
|
9
|
-
};
|
|
10
|
-
export declare function controlListenModeFromHost(host: unknown): ControlListenMode;
|
|
11
|
-
export declare function controlHostForListenMode(mode: ControlListenMode): "127.0.0.1" | "0.0.0.0";
|
|
12
|
-
export declare function managedBrowserSetupPlan(listenMode: ControlListenMode, browser: {
|
|
13
|
-
supported: boolean;
|
|
14
|
-
installed: boolean;
|
|
15
|
-
}): ManagedBrowserSetupPlan;
|
|
16
|
-
/** Walk the user through config.json step by step. Returns a process exit code. */
|
|
17
|
-
export declare function runSetup(): Promise<number>;
|
|
18
|
-
/** Read-only diagnostics. Returns a process exit code (0 ok, 1 on any failure). */
|
|
19
|
-
export declare function runDoctor(): Promise<number>;
|
|
20
|
-
export {};
|
package/dist/setup.js
DELETED
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `rynx setup` / `rynx doctor` — bootstrap + health check for the daemon home
|
|
3
|
-
* (`~/.rynx`). Replaces the old repo-bound `scripts/setup.sh`: config lives in
|
|
4
|
-
* `{RYNX_HOME}/config.json` and the CLI ships as a global binary, so this belongs
|
|
5
|
-
* here where it can also read the SQLite store directly. The interactive UI is
|
|
6
|
-
* rendered with `@clack/prompts`.
|
|
7
|
-
*
|
|
8
|
-
* rynx setup interactive, step-by-step wizard that writes ~/.rynx/config.json
|
|
9
|
-
* (falls back to writing defaults when stdin isn't a TTY)
|
|
10
|
-
* rynx doctor read-only diagnostics (creates nothing; non-zero exit on failure)
|
|
11
|
-
*/
|
|
12
|
-
import { spawnSync } from "node:child_process";
|
|
13
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
-
import { join } from "node:path";
|
|
15
|
-
import * as p from "@clack/prompts";
|
|
16
|
-
import { AGENT_RUNTIME_IDS, getRuntimeProfile, listAgentSpecs, loadConfig, resolveRuntimeHome, rynxAgentsDir, rynxConfigFile, rynxHome, } from "@rynx-ai/core";
|
|
17
|
-
import { listChannels } from "./channel-store.js";
|
|
18
|
-
import { resolveChromeForTestingRelease } from "./chrome-for-testing-release-resolver.js";
|
|
19
|
-
import { createChromeForTestingArtifactStore, isChromeForTestingHostSupported, } from "./chrome-for-testing-store.js";
|
|
20
|
-
import { dbPath } from "./db.js";
|
|
21
|
-
import { listInstances } from "./instance-store.js";
|
|
22
|
-
import { isRunnablePluginRecord, listPlugins } from "./plugin-store.js";
|
|
23
|
-
import { formatControlUrl } from "./pm2.js";
|
|
24
|
-
const MIN_NODE_MAJOR = 20;
|
|
25
|
-
export function controlListenModeFromHost(host) {
|
|
26
|
-
const normalized = typeof host === "string" ? host.trim().replace(/^\[|\]$/g, "") : "";
|
|
27
|
-
return normalized === "" ||
|
|
28
|
-
normalized === "127.0.0.1" ||
|
|
29
|
-
normalized === "::1" ||
|
|
30
|
-
normalized.toLowerCase() === "localhost"
|
|
31
|
-
? "loopback"
|
|
32
|
-
: "host";
|
|
33
|
-
}
|
|
34
|
-
export function controlHostForListenMode(mode) {
|
|
35
|
-
return mode === "host" ? "0.0.0.0" : "127.0.0.1";
|
|
36
|
-
}
|
|
37
|
-
export function managedBrowserSetupPlan(listenMode, browser) {
|
|
38
|
-
if (!browser.supported)
|
|
39
|
-
return { kind: "unsupported" };
|
|
40
|
-
if (browser.installed)
|
|
41
|
-
return { kind: "ready" };
|
|
42
|
-
return { kind: "offer", installByDefault: listenMode === "host" };
|
|
43
|
-
}
|
|
44
|
-
// ── rynx setup — interactive wizard ─────────────────────────────────────────
|
|
45
|
-
/** Walk the user through config.json step by step. Returns a process exit code. */
|
|
46
|
-
export async function runSetup() {
|
|
47
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
48
|
-
// Non-interactive (CI / piped): never block on a prompt — just ensure defaults.
|
|
49
|
-
if (!existsSync(rynxConfigFile()))
|
|
50
|
-
writeConfig({ HOST: "127.0.0.1", PORT: 3000, LOG_LEVEL: "info" });
|
|
51
|
-
const browser = inspectManagedBrowser();
|
|
52
|
-
console.log(`非交互环境:已确保 ${rynxConfigFile()} 存在(默认值)。` +
|
|
53
|
-
"在终端(TTY)下重跑 `rynx setup` 可分步配置,或直接编辑该文件。" +
|
|
54
|
-
(browser.supported && !browser.installed
|
|
55
|
-
? "\nSession Browser 尚未安装;需要时运行 `rynx browser install`。"
|
|
56
|
-
: ""));
|
|
57
|
-
return 0;
|
|
58
|
-
}
|
|
59
|
-
p.intro("rynx setup · 配置 ~/.rynx");
|
|
60
|
-
const cfg = readConfig();
|
|
61
|
-
// Runtimes: show status, offer login for any logged-out codex/traex, pick default.
|
|
62
|
-
let states = AGENT_RUNTIME_IDS.map(runtimeState);
|
|
63
|
-
p.note(states.map((s) => `${statusGlyph(s)} ${s.id.padEnd(7)} ${runtimeHint(s)}`).join("\n"), "运行时");
|
|
64
|
-
for (const s of states) {
|
|
65
|
-
if (s.installed && s.login === "logged-out" && s.id !== "claude") {
|
|
66
|
-
const yes = await p.confirm({ message: `现在登录 ${s.id}(${s.profile.loginCommand})?`, initialValue: false });
|
|
67
|
-
if (p.isCancel(yes))
|
|
68
|
-
return bail();
|
|
69
|
-
if (yes)
|
|
70
|
-
spawnSync(s.bin, ["login"], { stdio: "inherit" });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const claude = states.find((s) => s.id === "claude");
|
|
74
|
-
if (claude?.installed && claude.login === "logged-out") {
|
|
75
|
-
p.log.info("claude 登录:运行 `claude /login`,或设置 ANTHROPIC_API_KEY 后重来");
|
|
76
|
-
}
|
|
77
|
-
states = AGENT_RUNTIME_IDS.map(runtimeState); // re-probe after any login
|
|
78
|
-
const installed = states.filter((s) => s.installed);
|
|
79
|
-
if (installed.length === 0) {
|
|
80
|
-
p.log.warn("没有检测到运行时;装好 codex / traex / claude 之一后可设默认。");
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
const current = typeof cfg.AGENT_RUNTIME === "string" ? cfg.AGENT_RUNTIME : undefined;
|
|
84
|
-
const initial = current ?? installed.find((s) => s.login === "logged-in")?.id ?? installed[0].id;
|
|
85
|
-
const runtime = await p.select({
|
|
86
|
-
message: "默认运行时 AGENT_RUNTIME",
|
|
87
|
-
initialValue: initial,
|
|
88
|
-
options: installed.map((s) => ({ value: s.id, label: s.id, hint: runtimeHint(s) })),
|
|
89
|
-
});
|
|
90
|
-
if (p.isCancel(runtime))
|
|
91
|
-
return bail();
|
|
92
|
-
cfg.AGENT_RUNTIME = runtime;
|
|
93
|
-
}
|
|
94
|
-
// HTTP port.
|
|
95
|
-
const port = await p.text({
|
|
96
|
-
message: "HTTP 端口 PORT",
|
|
97
|
-
placeholder: "3000",
|
|
98
|
-
initialValue: String(cfg.PORT ?? 3000),
|
|
99
|
-
validate: (v) => {
|
|
100
|
-
const n = Number(v);
|
|
101
|
-
if (!Number.isInteger(n) || n <= 0 || n > 65535)
|
|
102
|
-
return "请输入 1–65535 之间的端口";
|
|
103
|
-
return undefined;
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
if (p.isCancel(port))
|
|
107
|
-
return bail();
|
|
108
|
-
cfg.PORT = Number(port);
|
|
109
|
-
const listenMode = await p.select({
|
|
110
|
-
message: "控制台访问范围 HOST",
|
|
111
|
-
initialValue: controlListenModeFromHost(cfg.HOST),
|
|
112
|
-
options: [
|
|
113
|
-
{
|
|
114
|
-
value: "loopback",
|
|
115
|
-
label: "仅本机(Loopback,推荐)",
|
|
116
|
-
hint: "绑定 127.0.0.1",
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
value: "host",
|
|
120
|
-
label: "网络访问(Host)",
|
|
121
|
-
hint: "绑定 0.0.0.0,可信网络可通过机器 IP 访问",
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
});
|
|
125
|
-
if (p.isCancel(listenMode))
|
|
126
|
-
return bail();
|
|
127
|
-
cfg.HOST = controlHostForListenMode(listenMode);
|
|
128
|
-
cfg.LOG_LEVEL = cfg.LOG_LEVEL ?? "info";
|
|
129
|
-
const browserBeforeSetup = inspectManagedBrowser();
|
|
130
|
-
const browserPlan = managedBrowserSetupPlan(listenMode, {
|
|
131
|
-
supported: browserBeforeSetup.supported,
|
|
132
|
-
installed: Boolean(browserBeforeSetup.installed),
|
|
133
|
-
});
|
|
134
|
-
let installBrowser = false;
|
|
135
|
-
if (browserPlan.kind === "ready") {
|
|
136
|
-
p.log.success(`Session Browser 已就绪 · Chrome for Testing ${browserBeforeSetup.installed.version}`);
|
|
137
|
-
}
|
|
138
|
-
else if (browserPlan.kind === "unsupported") {
|
|
139
|
-
p.log.info(`当前平台 ${process.platform}-${process.arch} 不支持 managed Chrome for Testing;跳过 Browser 安装。`);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
p.note([
|
|
143
|
-
"Session Browser 让 agent 在当前 Runtime 上打开和操作网页。",
|
|
144
|
-
listenMode === "host"
|
|
145
|
-
? "网络访问模式下,外部浏览器不能提供 Desktop Browser Host,因此推荐安装无头 Browser。"
|
|
146
|
-
: "桌面 App 可使用内置 Browser;独立 daemon 或远端 Runtime 仍需要无头 Browser。",
|
|
147
|
-
"安装会从 Chrome for Testing 官方源下载浏览器,不会改动系统浏览器。",
|
|
148
|
-
...(process.platform === "linux"
|
|
149
|
-
? ["Linux 的动态库和字体依赖仍需由系统或主机镜像提供。"]
|
|
150
|
-
: []),
|
|
151
|
-
].join("\n"), "Session Browser(可选)");
|
|
152
|
-
const choice = await p.confirm({
|
|
153
|
-
message: "现在安装 managed Chrome for Testing?",
|
|
154
|
-
initialValue: browserPlan.installByDefault,
|
|
155
|
-
});
|
|
156
|
-
if (p.isCancel(choice))
|
|
157
|
-
return bail();
|
|
158
|
-
installBrowser = choice;
|
|
159
|
-
}
|
|
160
|
-
writeConfig(cfg);
|
|
161
|
-
p.log.success(`已写入 ${rynxConfigFile()}(chmod 600)`);
|
|
162
|
-
p.log.message(`HOST=${cfg.HOST} PORT=${cfg.PORT} AGENT_RUNTIME=${cfg.AGENT_RUNTIME ?? "(默认)"}`);
|
|
163
|
-
let browserReady = browserPlan.kind === "ready";
|
|
164
|
-
if (installBrowser) {
|
|
165
|
-
const spinner = p.spinner();
|
|
166
|
-
spinner.start("准备安装 Stable Chrome for Testing");
|
|
167
|
-
try {
|
|
168
|
-
const release = await resolveChromeForTestingRelease({
|
|
169
|
-
kind: "channel",
|
|
170
|
-
channel: "Stable",
|
|
171
|
-
});
|
|
172
|
-
const installedBrowser = await createChromeForTestingArtifactStore().installResolved(release, { onProgress: (message) => spinner.message(message) });
|
|
173
|
-
browserReady = true;
|
|
174
|
-
spinner.stop(`Session Browser 已就绪 · Chrome for Testing ${installedBrowser.version}`);
|
|
175
|
-
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
spinner.error("Session Browser 安装失败");
|
|
178
|
-
p.log.warn(`${error instanceof Error ? error.message : String(error)}\n` +
|
|
179
|
-
"配置已保存;修复网络或系统依赖后运行 `rynx browser install` 重试。");
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else if (browserPlan.kind === "offer") {
|
|
183
|
-
p.log.info("已跳过 Browser 安装;需要时运行 `rynx browser install`。");
|
|
184
|
-
}
|
|
185
|
-
const url = formatControlUrl(String(cfg.HOST ?? "127.0.0.1"), Number(cfg.PORT ?? 3000));
|
|
186
|
-
p.note([
|
|
187
|
-
`启动常驻服务 rynx start`,
|
|
188
|
-
`打开控制台 ${url}`,
|
|
189
|
-
browserReady
|
|
190
|
-
? "Session Browser 已就绪"
|
|
191
|
-
: "启用 Browser rynx browser install",
|
|
192
|
-
`新建 agent rynx agent add <id>`,
|
|
193
|
-
`随时体检 rynx doctor`,
|
|
194
|
-
].join("\n"), "下一步");
|
|
195
|
-
p.outro("配置完成 🎉");
|
|
196
|
-
return 0;
|
|
197
|
-
}
|
|
198
|
-
// ── rynx doctor — read-only health check ────────────────────────────────────
|
|
199
|
-
/** Read-only diagnostics. Returns a process exit code (0 ok, 1 on any failure). */
|
|
200
|
-
export async function runDoctor() {
|
|
201
|
-
let warn = 0;
|
|
202
|
-
let fail = 0;
|
|
203
|
-
const home = rynxHome();
|
|
204
|
-
p.intro("rynx doctor · 只读体检");
|
|
205
|
-
p.note([
|
|
206
|
-
`RYNX_HOME ${home}`,
|
|
207
|
-
`config ${rynxConfigFile()}`,
|
|
208
|
-
`db ${dbPath()}`,
|
|
209
|
-
`agents ${rynxAgentsDir()}`,
|
|
210
|
-
`logs ${join(home, "logs")}`,
|
|
211
|
-
].join("\n"), "路径");
|
|
212
|
-
const major = Number(process.versions.node.split(".")[0]);
|
|
213
|
-
if (major >= MIN_NODE_MAJOR)
|
|
214
|
-
p.log.success(`Node.js v${process.versions.node}(要求 ≥ ${MIN_NODE_MAJOR})`);
|
|
215
|
-
else
|
|
216
|
-
(p.log.error(`Node.js v${process.versions.node} 过低,要求 ≥ ${MIN_NODE_MAJOR}`), fail++);
|
|
217
|
-
if (existsSync(rynxConfigFile()))
|
|
218
|
-
p.log.success(`config.json 已存在`);
|
|
219
|
-
else
|
|
220
|
-
(p.log.warn("缺少 config.json —— 运行 `rynx setup` 生成"), warn++);
|
|
221
|
-
try {
|
|
222
|
-
const config = loadConfig();
|
|
223
|
-
p.log.info(`HOST=${config.HOST} PORT=${config.PORT} LOG_LEVEL=${config.LOG_LEVEL} AGENT_RUNTIME=${config.AGENT_RUNTIME}`);
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
p.log.error(`配置解析失败:${error.message}`);
|
|
227
|
-
fail++;
|
|
228
|
-
}
|
|
229
|
-
let anyReady = false;
|
|
230
|
-
for (const s of AGENT_RUNTIME_IDS.map(runtimeState)) {
|
|
231
|
-
if (!s.installed)
|
|
232
|
-
p.log.info(`${s.id}:未安装(${s.bin} 不在 PATH)`);
|
|
233
|
-
else if (s.login === "logged-in")
|
|
234
|
-
(p.log.success(`${s.id}:已登录`), (anyReady = true));
|
|
235
|
-
else if (s.login === "logged-out")
|
|
236
|
-
(p.log.warn(`${s.id}:未登录 —— 运行 \`${s.profile.loginCommand}\``), warn++);
|
|
237
|
-
else
|
|
238
|
-
(p.log.warn(`${s.id}:已安装,登录状态待确认(若报鉴权错误,执行 \`${s.profile.loginCommand}\`)`), (anyReady = true));
|
|
239
|
-
}
|
|
240
|
-
if (!anyReady)
|
|
241
|
-
(p.log.error("没有就绪的运行时 —— 至少登录一个:codex login / traex login / claude /login"), fail++);
|
|
242
|
-
if (!existsSync(dbPath())) {
|
|
243
|
-
p.log.info("rynx.db 尚未创建(首次 `rynx start` 时生成)");
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
const plugins = listPlugins();
|
|
247
|
-
p.log.info(`插件:${plugins.length} 个${plugins.length ? `(${plugins.map((pl) => pl.name).join(", ")})` : ""}`);
|
|
248
|
-
const legacyPlugins = plugins.filter((plugin) => !isRunnablePluginRecord(plugin));
|
|
249
|
-
if (legacyPlugins.length > 0) {
|
|
250
|
-
p.log.warn(`需重新安装的旧插件:${legacyPlugins.map((plugin) => plugin.name).join(", ")}`);
|
|
251
|
-
warn++;
|
|
252
|
-
}
|
|
253
|
-
const channels = listChannels();
|
|
254
|
-
const configured = channels.filter((c) => c.options && Object.keys(c.options).length > 0).length;
|
|
255
|
-
p.log.info(`channel:${channels.length} 个(${configured} 已配置凭据) · instance:${listInstances().length} 个`);
|
|
256
|
-
if (channels.length === 0)
|
|
257
|
-
(p.log.warn("还没有 channel —— 在 Web 控制台新建并授权"), warn++);
|
|
258
|
-
}
|
|
259
|
-
p.log.info(`agent:${(await listAgentSpecs()).length} 个(${rynxAgentsDir()})`);
|
|
260
|
-
const browser = inspectManagedBrowser();
|
|
261
|
-
if (!browser.supported) {
|
|
262
|
-
p.log.info(`Session Browser:当前平台 ${process.platform}-${process.arch} 不受支持`);
|
|
263
|
-
}
|
|
264
|
-
else if (browser.installed) {
|
|
265
|
-
p.log.success(`Session Browser:Chrome for Testing ${browser.installed.version} 已安装`);
|
|
266
|
-
if (process.platform === "linux") {
|
|
267
|
-
p.log.info("Linux Browser 动态库和字体依赖由系统或主机镜像提供");
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
else if (browser.error) {
|
|
271
|
-
p.log.warn(`Session Browser 安装无效:${browser.error} —— 运行 \`rynx browser install\` 修复`);
|
|
272
|
-
warn++;
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
p.log.warn("Session Browser 未安装 —— 运行 `rynx browser install`");
|
|
276
|
-
warn++;
|
|
277
|
-
}
|
|
278
|
-
if (fail > 0) {
|
|
279
|
-
p.outro(`体检发现 ${fail} 个失败项(警告 ${warn})—— 处理后重跑 rynx doctor`);
|
|
280
|
-
return 1;
|
|
281
|
-
}
|
|
282
|
-
p.outro(warn > 0 ? `基本就绪,有 ${warn} 个警告` : "全部通过 ✓");
|
|
283
|
-
return 0;
|
|
284
|
-
}
|
|
285
|
-
function inspectManagedBrowser() {
|
|
286
|
-
if (!isChromeForTestingHostSupported())
|
|
287
|
-
return { supported: false };
|
|
288
|
-
try {
|
|
289
|
-
return {
|
|
290
|
-
supported: true,
|
|
291
|
-
installed: createChromeForTestingArtifactStore().readActive(),
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
catch (error) {
|
|
295
|
-
return {
|
|
296
|
-
supported: true,
|
|
297
|
-
installed: undefined,
|
|
298
|
-
error: error instanceof Error ? error.message : String(error),
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
function runtimeState(id) {
|
|
303
|
-
const profile = getRuntimeProfile(id);
|
|
304
|
-
const installed = onPath(profile.defaultBinary);
|
|
305
|
-
const login = !installed
|
|
306
|
-
? "logged-out"
|
|
307
|
-
: id === "claude"
|
|
308
|
-
? claudeAuthState(profile)
|
|
309
|
-
: cliLoginState(profile.defaultBinary);
|
|
310
|
-
return { id, bin: profile.defaultBinary, profile, installed, login };
|
|
311
|
-
}
|
|
312
|
-
function statusGlyph(s) {
|
|
313
|
-
if (!s.installed)
|
|
314
|
-
return "○";
|
|
315
|
-
return s.login === "logged-in" ? "●" : "◍";
|
|
316
|
-
}
|
|
317
|
-
function runtimeHint(s) {
|
|
318
|
-
if (!s.installed)
|
|
319
|
-
return `未安装(${s.bin} 不在 PATH)`;
|
|
320
|
-
if (s.login === "logged-in")
|
|
321
|
-
return "已登录";
|
|
322
|
-
if (s.login === "logged-out")
|
|
323
|
-
return "已安装,未登录";
|
|
324
|
-
return "已安装,状态待确认";
|
|
325
|
-
}
|
|
326
|
-
/** Is `bin` runnable on PATH? Probe with `--version` (ENOENT ⇒ not installed). */
|
|
327
|
-
function onPath(bin) {
|
|
328
|
-
const result = spawnSync(bin, ["--version"], { stdio: "ignore", timeout: 8000 });
|
|
329
|
-
return !result.error && result.status === 0;
|
|
330
|
-
}
|
|
331
|
-
/** Parse `<bin> login status` (codex/traex) into a tri-state. */
|
|
332
|
-
function cliLoginState(bin) {
|
|
333
|
-
const result = spawnSync(bin, ["login", "status"], { encoding: "utf8", timeout: 12000 });
|
|
334
|
-
const out = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
335
|
-
if (/Logged in using/i.test(out))
|
|
336
|
-
return "logged-in";
|
|
337
|
-
if (/not logged in|logged out/i.test(out))
|
|
338
|
-
return "logged-out";
|
|
339
|
-
return "unknown";
|
|
340
|
-
}
|
|
341
|
-
/** Claude has no `login status`; auth is an API-key env var or the `~/.claude` config dir. */
|
|
342
|
-
function claudeAuthState(profile) {
|
|
343
|
-
if (process.env.ANTHROPIC_API_KEY?.trim() || process.env.ANTHROPIC_AUTH_TOKEN?.trim())
|
|
344
|
-
return "logged-in";
|
|
345
|
-
return existsSync(resolveRuntimeHome(profile)) ? "unknown" : "logged-out";
|
|
346
|
-
}
|
|
347
|
-
function readConfig() {
|
|
348
|
-
const file = rynxConfigFile();
|
|
349
|
-
if (!existsSync(file))
|
|
350
|
-
return {};
|
|
351
|
-
try {
|
|
352
|
-
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
353
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
354
|
-
}
|
|
355
|
-
catch {
|
|
356
|
-
return {};
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
function writeConfig(cfg) {
|
|
360
|
-
const file = rynxConfigFile();
|
|
361
|
-
mkdirSync(rynxHome(), { recursive: true });
|
|
362
|
-
writeFileSync(file, `${JSON.stringify(cfg, null, 2)}\n`);
|
|
363
|
-
try {
|
|
364
|
-
chmodSync(file, 0o600);
|
|
365
|
-
}
|
|
366
|
-
catch {
|
|
367
|
-
/* best-effort on platforms without POSIX modes */
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
/** User pressed Ctrl-C mid-wizard: print a cancel note and exit cleanly. */
|
|
371
|
-
function bail() {
|
|
372
|
-
p.cancel("已取消,未保存改动。");
|
|
373
|
-
return 0;
|
|
374
|
-
}
|
package/dist/update.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export interface UpdateOptions {
|
|
2
|
-
check?: boolean;
|
|
3
|
-
/** With `check`, emit a typed {@link UpdateCheck} as JSON instead of a human line. */
|
|
4
|
-
json?: boolean;
|
|
5
|
-
version?: string;
|
|
6
|
-
}
|
|
7
|
-
export type UpdateCheck = {
|
|
8
|
-
status: "up_to_date";
|
|
9
|
-
current: string;
|
|
10
|
-
} | {
|
|
11
|
-
status: "behind";
|
|
12
|
-
current: string;
|
|
13
|
-
latest: string;
|
|
14
|
-
} | {
|
|
15
|
-
status: "error";
|
|
16
|
-
detail: string;
|
|
17
|
-
};
|
|
18
|
-
/** Is `latest` a newer release than `current`? Numeric major.minor.patch (prerelease ignored). */
|
|
19
|
-
export declare function isNewer(latest: string, current: string): boolean;
|
|
20
|
-
/** Typed `--check` result a channel consumes via `--check --json`. */
|
|
21
|
-
export declare function buildUpdateCheck(current: string, latest: string | null): UpdateCheck;
|
|
22
|
-
/** Format the one-line, human-readable status emitted by a bare `--check`. */
|
|
23
|
-
export declare function checkStatusLine(current: string, latest: string | null): string;
|
|
24
|
-
/** Run `rynx update`. Returns a process exit code. */
|
|
25
|
-
export declare function runUpdate(opts: UpdateOptions): Promise<number>;
|