@openagt/dashboard 0.10.0 → 0.12.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/README.md +1 -6
- package/dist/built-in.d.ts +18 -2
- package/dist/built-in.d.ts.map +1 -1
- package/dist/built-in.js +29 -6
- package/dist/built-in.js.map +1 -1
- package/dist/cli.d.ts +4 -10
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -67
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -4
- package/dist/client.js.map +1 -1
- package/dist/clone-project.d.ts +69 -0
- package/dist/clone-project.d.ts.map +1 -0
- package/dist/clone-project.js +124 -0
- package/dist/clone-project.js.map +1 -0
- package/dist/daemon-runtime.d.ts +12 -12
- package/dist/daemon-runtime.d.ts.map +1 -1
- package/dist/daemon-runtime.js +96 -35
- package/dist/daemon-runtime.js.map +1 -1
- package/dist/daemon.d.ts +3 -14
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +15 -26
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bridge-endpoints.d.ts +5 -5
- package/dist/dashboard/bridge-endpoints.js +5 -5
- package/dist/dashboard/http.d.ts +1 -1
- package/dist/dashboard/http.js +1 -1
- package/dist/dashboard/machine-call.d.ts +10 -0
- package/dist/dashboard/machine-call.d.ts.map +1 -0
- package/dist/dashboard/machine-call.js +86 -0
- package/dist/dashboard/machine-call.js.map +1 -0
- package/dist/dashboard/module-serve.d.ts +6 -0
- package/dist/dashboard/module-serve.d.ts.map +1 -1
- package/dist/dashboard/module-serve.js +24 -8
- package/dist/dashboard/module-serve.js.map +1 -1
- package/dist/dashboard/relay-endpoints.d.ts +26 -17
- package/dist/dashboard/relay-endpoints.d.ts.map +1 -1
- package/dist/dashboard/relay-endpoints.js +70 -27
- package/dist/dashboard/relay-endpoints.js.map +1 -1
- package/dist/dashboard/remote-run.d.ts +77 -32
- package/dist/dashboard/remote-run.d.ts.map +1 -1
- package/dist/dashboard/remote-run.js +120 -42
- package/dist/dashboard/remote-run.js.map +1 -1
- package/dist/dashboard/rpc-serve.d.ts +28 -25
- package/dist/dashboard/rpc-serve.d.ts.map +1 -1
- package/dist/dashboard/rpc-serve.js +26 -22
- package/dist/dashboard/rpc-serve.js.map +1 -1
- package/dist/dashboard/screen.d.ts +53 -0
- package/dist/dashboard/screen.d.ts.map +1 -0
- package/dist/dashboard/screen.js +175 -0
- package/dist/dashboard/screen.js.map +1 -0
- package/dist/dashboard/server.d.ts +18 -19
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +57 -84
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/types.d.ts +11 -16
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/dashboard/web-start-endpoints.d.ts +2 -2
- package/dist/dashboard/web-start-endpoints.js +1 -1
- package/dist/dashboard-bundle/assets/main-BHMlP40v.css +2 -0
- package/dist/dashboard-bundle/assets/main-D0qZC1r-.js +140 -0
- package/dist/dashboard-bundle/assets/{module-gKz-ZvkG.js → module-ZjyA5WUg.js} +4 -4
- package/dist/dashboard-bundle/host/module.js +1 -1
- package/dist/dashboard-bundle/index.html +3 -3
- package/dist/dashboard-rpc/context.d.ts +4 -4
- package/dist/dashboard-rpc/context.js +5 -5
- package/dist/dashboard-rpc/context.js.map +1 -1
- package/dist/dashboard-rpc/control.d.ts +1 -1
- package/dist/dashboard-rpc/control.js +7 -7
- package/dist/dashboard-rpc/control.js.map +1 -1
- package/dist/dashboard-rpc/events.d.ts +1 -1
- package/dist/dashboard-rpc/events.js +1 -1
- package/dist/dashboard-rpc/index.d.ts +3 -3
- package/dist/dashboard-rpc/index.d.ts.map +1 -1
- package/dist/dashboard-rpc/index.js +5 -5
- package/dist/dashboard-rpc/index.js.map +1 -1
- package/dist/dashboard-rpc/machines.d.ts +52 -0
- package/dist/dashboard-rpc/machines.d.ts.map +1 -0
- package/dist/dashboard-rpc/machines.js +82 -0
- package/dist/dashboard-rpc/machines.js.map +1 -0
- package/dist/dashboard-rpc/modules.d.ts +12 -4
- package/dist/dashboard-rpc/modules.d.ts.map +1 -1
- package/dist/dashboard-rpc/modules.js +24 -5
- package/dist/dashboard-rpc/modules.js.map +1 -1
- package/dist/dashboard-rpc/projects.d.ts +18 -0
- package/dist/dashboard-rpc/projects.d.ts.map +1 -1
- package/dist/dashboard-rpc/projects.js +27 -5
- package/dist/dashboard-rpc/projects.js.map +1 -1
- package/dist/dashboard-rpc/reads.d.ts +3 -4
- package/dist/dashboard-rpc/reads.d.ts.map +1 -1
- package/dist/dashboard-rpc/reads.js +5 -6
- package/dist/dashboard-rpc/reads.js.map +1 -1
- package/dist/dashboard-rpc/relay-agent.d.ts +3 -3
- package/dist/dashboard-rpc/relay-agent.js +3 -3
- package/dist/dashboard-rpc/relay-dispatch.d.ts +4 -4
- package/dist/dashboard-rpc/relay-dispatch.d.ts.map +1 -1
- package/dist/dashboard-rpc/relay-dispatch.js +7 -7
- package/dist/dashboard-rpc/relay-dispatch.js.map +1 -1
- package/dist/dashboard-rpc/test-context.js +1 -1
- package/dist/dashboard-rpc/test-context.js.map +1 -1
- package/dist/events.d.ts +4 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/loopback-host.d.ts +3 -5
- package/dist/loopback-host.d.ts.map +1 -1
- package/dist/loopback-host.js +3 -5
- package/dist/loopback-host.js.map +1 -1
- package/dist/machine-link.d.ts +21 -0
- package/dist/machine-link.d.ts.map +1 -0
- package/dist/machine-link.js +20 -0
- package/dist/machine-link.js.map +1 -0
- package/dist/module-server.d.ts +1 -1
- package/dist/module-types/dashboard/components/QrCode.d.ts +8 -0
- package/dist/module-types/dashboard/lib/draft-handoff.d.ts +5 -9
- package/dist/module-types/dashboard/module/index.d.ts +56 -4
- package/dist/module-types/dashboard/rpc/modules.d.ts +1 -0
- package/dist/module-types/src/built-in.d.ts +18 -2
- package/dist/module-types/src/client.d.ts +2 -1
- package/dist/module-types/src/clone-project.d.ts +68 -0
- package/dist/module-types/src/dashboard/bridge-endpoints.d.ts +5 -5
- package/dist/module-types/src/dashboard/http.d.ts +1 -1
- package/dist/module-types/src/dashboard/machine-call.d.ts +9 -0
- package/dist/module-types/src/dashboard/module-serve.d.ts +6 -0
- package/dist/module-types/src/dashboard/remote-run.d.ts +77 -32
- package/dist/module-types/src/dashboard/rpc-serve.d.ts +28 -25
- package/dist/module-types/src/dashboard/types.d.ts +11 -16
- package/dist/module-types/src/dashboard-rpc/context.d.ts +4 -4
- package/dist/module-types/src/dashboard-rpc/control.d.ts +1 -1
- package/dist/module-types/src/dashboard-rpc/events.d.ts +1 -1
- package/dist/module-types/src/dashboard-rpc/index.d.ts +3 -3
- package/dist/module-types/src/dashboard-rpc/machines.d.ts +51 -0
- package/dist/module-types/src/dashboard-rpc/modules.d.ts +12 -4
- package/dist/module-types/src/dashboard-rpc/projects.d.ts +18 -0
- package/dist/module-types/src/dashboard-rpc/reads.d.ts +3 -4
- package/dist/module-types/src/dashboard-rpc/relay-agent.d.ts +3 -3
- package/dist/module-types/src/events.d.ts +4 -3
- package/dist/module-types/src/loopback-host.d.ts +3 -5
- package/dist/module-types/src/machine-link.d.ts +20 -0
- package/dist/module-types/src/pick-directory.d.ts +2 -0
- package/dist/module-types/src/project-modules.d.ts +12 -3
- package/dist/module-types/src/registry.d.ts +59 -16
- package/dist/module-types/src/repository-address.d.ts +22 -0
- package/dist/module-types/src/screens.d.ts +13 -0
- package/dist/module-types/src/store/agent-store.d.ts +2 -2
- package/dist/module-types/src/version.d.ts +1 -0
- package/dist/package-services.d.ts +27 -0
- package/dist/package-services.d.ts.map +1 -0
- package/dist/package-services.js +62 -0
- package/dist/package-services.js.map +1 -0
- package/dist/pick-directory.d.ts +2 -0
- package/dist/pick-directory.d.ts.map +1 -1
- package/dist/pick-directory.js +7 -1
- package/dist/pick-directory.js.map +1 -1
- package/dist/project-modules.d.ts +12 -3
- package/dist/project-modules.d.ts.map +1 -1
- package/dist/project-modules.js +20 -2
- package/dist/project-modules.js.map +1 -1
- package/dist/registry.d.ts +59 -16
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +91 -20
- package/dist/registry.js.map +1 -1
- package/dist/repository-address.d.ts +23 -0
- package/dist/repository-address.d.ts.map +1 -0
- package/dist/repository-address.js +38 -0
- package/dist/repository-address.js.map +1 -0
- package/dist/screens.d.ts +14 -0
- package/dist/screens.d.ts.map +1 -0
- package/dist/screens.js +40 -0
- package/dist/screens.js.map +1 -0
- package/dist/store/agent-store.d.ts +2 -2
- package/dist/store/agent-store.d.ts.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +26 -0
- package/dist/version.js.map +1 -0
- package/package.json +15 -11
- package/dist/dashboard-bundle/assets/main-Q7JMdMJI.css +0 -2
- package/dist/dashboard-bundle/assets/main-fDZWGOub.js +0 -140
- package/dist/dashboard-rpc/devices.d.ts +0 -9
- package/dist/dashboard-rpc/devices.d.ts.map +0 -1
- package/dist/dashboard-rpc/devices.js +0 -12
- package/dist/dashboard-rpc/devices.js.map +0 -1
- package/dist/install.d.ts +0 -31
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js +0 -54
- package/dist/install.js.map +0 -1
- package/dist/module-types/src/dashboard-rpc/devices.d.ts +0 -8
- package/dist/module-types/src/openagent-gitignore.d.ts +0 -11
- package/dist/openagent-gitignore.d.ts +0 -12
- package/dist/openagent-gitignore.d.ts.map +0 -1
- package/dist/openagent-gitignore.js +0 -19
- package/dist/openagent-gitignore.js.map +0 -1
|
@@ -22,18 +22,18 @@ export declare function resolveProjectPath(projectId: string): Promise<string |
|
|
|
22
22
|
export declare function resolveAgentPath(projectId: string, agentId?: string): Promise<string | undefined>;
|
|
23
23
|
/**
|
|
24
24
|
* The in-memory {@link EventsSource} (#426). It answers only for a run this daemon is relaying
|
|
25
|
-
* from a
|
|
25
|
+
* from a saved machine (#1067) — such a run has no diary on this machine, since it works in a
|
|
26
26
|
* checkout over there — and returns undefined for an ordinary local run, whose diary `onEvents`
|
|
27
27
|
* tails off disk.
|
|
28
28
|
*/
|
|
29
29
|
export declare function contextEventsSource(): EventsSource;
|
|
30
30
|
/**
|
|
31
31
|
* The relayed-agent lookup (#1067 slice 2). A run-scoped RPC uses it to tell an ordinary local agent
|
|
32
|
-
* (resolve a local checkout) from one running on a
|
|
32
|
+
* (resolve a local checkout) from one running on a saved machine (forward the call there).
|
|
33
33
|
*
|
|
34
34
|
* The one accessor with a default rather than a throw, because "unwired" has a real meaning here:
|
|
35
|
-
* a call arriving over `/_relay/rpc` is the *
|
|
36
|
-
* local to that
|
|
35
|
+
* a call arriving over `/_relay/rpc` is the *machine* side of the relay, and the agent it names is
|
|
36
|
+
* local to that machine. Forwarding it onward would be a loop, so the honest answer there is that
|
|
37
37
|
* nothing is relayed from here.
|
|
38
38
|
*/
|
|
39
39
|
export declare function contextRemote(): RemoteAgents;
|
|
@@ -65,7 +65,7 @@ export declare function sendRemoveWorktree(projectId: string, agentId: string):
|
|
|
65
65
|
export declare function sendDeleteAgent(projectId: string, agentId: string): Promise<DeleteAgentResult>;
|
|
66
66
|
/**
|
|
67
67
|
* Start a run in the project (#405, #1774): the project's own `start` hook line, reached through
|
|
68
|
-
* the daemon's wired `startAgent` (which relays to a
|
|
68
|
+
* the daemon's wired `startAgent` (which relays to a saved machine when the options name
|
|
69
69
|
* one). Answers the id of the run the hook began, or why there is none: a project without the
|
|
70
70
|
* line cannot start a run from here.
|
|
71
71
|
*/
|
|
@@ -28,7 +28,7 @@ export type LiveFeedEvent = OpenAgentEvent | StreamSync | PartialMessage;
|
|
|
28
28
|
* The `agentId` names the run whose diary is followed; without one there is nothing to stream.
|
|
29
29
|
*
|
|
30
30
|
* Two sources, chosen by what is wired. An in-memory stream wins: an agent the daemon is relaying
|
|
31
|
-
* from a
|
|
31
|
+
* from a machine (#1067). Otherwise the on-disk log. The daemon's source answers only for relayed
|
|
32
32
|
* runs, so an ordinary local agent falls through to tailing the log.
|
|
33
33
|
*
|
|
34
34
|
* Only the on-disk tail sends the {@link StreamSync} marker: the in-memory sources have no replay
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { onAgents, onAgent, onAgentsDoing, onDocs, onQueue, onOverview, onRecentAgents, onInterventions, onOpenQuestions, onActivity, onDashboard, onGitHostHome, onRepositoryOffer, onGitStatus, onProjectFiles, onRetainedWorktrees, onAgentWorktree, onAgentHandoff, onBridgeQuestion, onBridgeStatus, onBridgeToken, onBridgeEvents, onBridgeAnswer, onBridgeBrowser } from './reads.js';
|
|
2
2
|
export { sendStop, sendChoice, sendBridgeAnswer, sendBridgeAnswerCancel, sendBridgeBrowser, sendMessage, sendStart, sendOpenInApp, sendRemoveWorktree, sendDeleteAgent, sendOpenPullRequest, sendPush, sendMergeBranch, sendMerge, sendCreateRepository } from './control.js';
|
|
3
3
|
export { streamAgentEvents, type LiveFeedEvent, type PartialMessage, type StreamSync } from './events.js';
|
|
4
|
-
export { onProjects, sendAddProject, sendRemoveProject, onRecordsReach, sendShareRecords, sendPickProjectDirectory, onOnboarding, onCommands, onStartCheck, type ProjectLauncher } from './projects.js';
|
|
4
|
+
export { onProjects, sendAddProject, onCloneTarget, sendAddProjectFromAddress, sendRemoveProject, onRecordsReach, sendShareRecords, sendPickProjectDirectory, onOnboarding, onCommands, onStartCheck, type ProjectLauncher } from './projects.js';
|
|
5
5
|
export { onPreferences, savePreferences, patchPreferences, onProjectPresets, saveProjectPresets, onEditors, type SavePreferencesResult, type PatchPreferencesResult, } from './preferences.js';
|
|
6
6
|
export { type EditorInfo } from '../dashboard/open-in-app.js';
|
|
7
7
|
export { onQuota } from './quota.js';
|
|
8
8
|
export { onModels } from './models.js';
|
|
9
|
-
export {
|
|
10
|
-
export { onModules, runModuleCommand, readModule, type DashboardModule, type ModuleCommandResult, type ModuleReadResult } from './modules.js';
|
|
9
|
+
export { onMachines, sendAddMachine, sendRemoveMachine, onMachinesReachable, onMachineVersions, type Machine, type AddMachineResult, type MachineVersions } from './machines.js';
|
|
10
|
+
export { onModules, runModuleCommand, runComputerCommand, readModule, type DashboardModule, type ModuleCommandResult, type ModuleReadResult } from './modules.js';
|
|
11
11
|
export { onProjectSkills, sendChangeSkills, sendCommitSkills, type ProjectSkills, type ProjectSkill, type ChangeSkillsResult } from './skills.js';
|
|
12
12
|
import { streamAgentEvents } from './events.js';
|
|
13
13
|
/** One RPC: called with whatever the browser sent, answering with whatever JSON.stringify keeps. */
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** A saved machine as the browser sees it: no key. */
|
|
2
|
+
export interface Machine {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
url: string;
|
|
6
|
+
}
|
|
7
|
+
export type AddMachineResult = {
|
|
8
|
+
ok: true;
|
|
9
|
+
machine: Machine;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
14
|
+
/** The saved machines, newest first. */
|
|
15
|
+
export declare function onMachines(): Promise<Machine[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Save the machine a pasted link names: the link another OpenAgent gives for a new device. This
|
|
18
|
+
* computer is let in there with the link's code, once, and keeps the key it is answered. Adding
|
|
19
|
+
* a machine again, with a new link, replaces its name and the key, and the key it had there
|
|
20
|
+
* before is taken out.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sendAddMachine(pasted: string, label?: string): Promise<AddMachineResult>;
|
|
23
|
+
export type RemoveMachineResult = {
|
|
24
|
+
ok: true;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Take a saved machine off the list, and this computer out of the machine: its key there stops
|
|
31
|
+
* working. Not while a run is at work there, which is read with that key. Taking the key out is
|
|
32
|
+
* not waited for: a machine that cannot be reached right now keeps it until this computer is
|
|
33
|
+
* removed there, among its devices.
|
|
34
|
+
*/
|
|
35
|
+
export declare function sendRemoveMachine(id: string): Promise<RemoveMachineResult>;
|
|
36
|
+
/** Whether each saved machine answers right now, by id: one short call to each, with this computer's key. */
|
|
37
|
+
export declare function onMachinesReachable(): Promise<Record<string, boolean>>;
|
|
38
|
+
/** This computer's OpenAgent, and the one each saved machine runs. */
|
|
39
|
+
export interface MachineVersions {
|
|
40
|
+
/** This computer's own. */
|
|
41
|
+
version: string;
|
|
42
|
+
/** Each saved machine, with its version when it answers and says. */
|
|
43
|
+
machines: (Machine & {
|
|
44
|
+
version?: string;
|
|
45
|
+
})[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The saved machines with the OpenAgent each runs, beside this computer's own: how a page tells
|
|
49
|
+
* that a machine fell behind this computer. One short call to each, with this computer's key.
|
|
50
|
+
*/
|
|
51
|
+
export declare function onMachineVersions(): Promise<MachineVersions>;
|
|
@@ -6,13 +6,14 @@ export type { ModuleReadResult } from '../dashboard/module-host.js';
|
|
|
6
6
|
export interface DashboardModule {
|
|
7
7
|
/** The package that brings it. */
|
|
8
8
|
package: string;
|
|
9
|
-
/** The URL of its browser module, served from the first project that has it. */
|
|
9
|
+
/** The URL of its browser module, served from the first project that has it, or from OpenAgent's own copy for one of the computer's. */
|
|
10
10
|
url: string;
|
|
11
|
-
/** The registered projects whose packages include it, in the registry's order. */
|
|
11
|
+
/** The registered projects whose packages include it, in the registry's order; none for one of the computer's, whose commands run in no project. */
|
|
12
12
|
projects: string[];
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Every module
|
|
15
|
+
* Every module the dashboard loads (#1774), one per package. First the computer's, which are
|
|
16
|
+
* there with no project added. Then every module any registered project brings, with the projects
|
|
16
17
|
* that have it: with no project picked the sidebar and the pages are every project's, and the
|
|
17
18
|
* dashboard narrows them itself to a picked project's. A package several projects install is loaded once, from
|
|
18
19
|
* the first of them in the registry's order; its page then reads each project through that
|
|
@@ -34,11 +35,18 @@ export declare function onModules(): Promise<DashboardModule[]>;
|
|
|
34
35
|
* write only at the next sync.
|
|
35
36
|
*/
|
|
36
37
|
export declare function runModuleCommand(projectId: string, pkg: string, args: string[], command?: string, acts?: boolean): Promise<ModuleCommandResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Run one of the commands of a package that is this computer's, in no project, and answer its
|
|
40
|
+
* JSON output: how the door's page and the servers' page read and change what they keep, which is
|
|
41
|
+
* in the person's home folder, where the command runs. Refused for any other package: a project's
|
|
42
|
+
* module runs its commands in its project ({@link runModuleCommand}).
|
|
43
|
+
*/
|
|
44
|
+
export declare function runComputerCommand(pkg: string, args: string[], command?: string): Promise<ModuleCommandResult>;
|
|
37
45
|
/**
|
|
38
46
|
* Call read `name` of a module's server part in one project: how a module's browser part reads
|
|
39
47
|
* what a command cannot answer fast enough. Refused for an unknown project, a package that is not
|
|
40
48
|
* a module of that project, and a module with no server part. A read whose input names a run this
|
|
41
|
-
* daemon relays to a
|
|
49
|
+
* daemon relays to a saved machine (`input.agentId`) is read over there, by that machine's own
|
|
42
50
|
* copy of the module, since the run's checkout is there.
|
|
43
51
|
*/
|
|
44
52
|
export declare function readModule(projectId: string, pkg: string, name: string, input: unknown): Promise<ModuleReadResult>;
|
|
@@ -15,6 +15,22 @@ export declare function onProjects(): Promise<ProjectSummary[]>;
|
|
|
15
15
|
* repository's remote. Nothing is pushed for a project added with `false`.
|
|
16
16
|
*/
|
|
17
17
|
export declare function sendAddProject(path: string, share: boolean): Promise<AddProjectResult>;
|
|
18
|
+
/** Where the repository a person typed the address of would be cloned to on this computer, or why what was typed is no address: asked before anything is cloned. */
|
|
19
|
+
export declare function onCloneTarget(address: string): Promise<{
|
|
20
|
+
ok: true;
|
|
21
|
+
address: string;
|
|
22
|
+
path: string;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
error: string;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Add a project by its repository's address, for a computer that does not have its folder: the
|
|
29
|
+
* repository is cloned into `~/projects/<its name>` with the logins this computer has, and the
|
|
30
|
+
* folder is then added as {@link sendAddProject} adds one. A folder already there with this
|
|
31
|
+
* repository in it is added as it is. The answer says where the project is.
|
|
32
|
+
*/
|
|
33
|
+
export declare function sendAddProjectFromAddress(address: string, share: boolean): Promise<AddProjectResult>;
|
|
18
34
|
/**
|
|
19
35
|
* Remove a project from the dashboard: it leaves the Projects list. Nothing in its folder is
|
|
20
36
|
* deleted unless `files` is true: then what OpenAgent left there is removed too, and the answer
|
|
@@ -58,6 +74,8 @@ export interface ProjectLauncher {
|
|
|
58
74
|
gitHost: boolean;
|
|
59
75
|
/** Whether the project's repository has an `origin` remote; without one nothing can be published, so the publish menu stops at the commit. */
|
|
60
76
|
remote: boolean;
|
|
77
|
+
/** The address the project's repository was cloned from, the name another machine knows the project by; absent, the project cannot be sent to one. */
|
|
78
|
+
address?: string;
|
|
61
79
|
/**
|
|
62
80
|
* The two branches an agent can start from here, for the launcher's "start from" chip: `main`,
|
|
63
81
|
* the name of origin's default branch, and `local`, the branch the project's folder is on now.
|
|
@@ -31,7 +31,7 @@ import type { BridgeAnswer, BridgeContact, BridgeVersion } from '../dashboard/br
|
|
|
31
31
|
* may have just self-healed a dead agent to `stopped` (#716), and that freshly-archived row can
|
|
32
32
|
* lag `listAgents` by a poll — keeping it regardless leaves the row visible with no flicker.
|
|
33
33
|
*
|
|
34
|
-
* An agent relayed to a
|
|
34
|
+
* An agent relayed to a saved machine (#1067) lives only in the daemon's memory, never on disk, so
|
|
35
35
|
* its in-memory stub is merged in too (#1077): that is what re-opens it after a dashboard reload
|
|
36
36
|
* instead of losing it.
|
|
37
37
|
*/
|
|
@@ -168,9 +168,8 @@ export declare function onBridgeStatus(): Promise<{
|
|
|
168
168
|
*
|
|
169
169
|
* Only while the bridge is on, so a daemon with the feature off never hands the secret to a
|
|
170
170
|
* page. Revealing it here is not a new exposure: anyone who can load this dashboard can already
|
|
171
|
-
* start runs on this machine
|
|
172
|
-
*
|
|
173
|
-
* `~/.openagent.json` and copy a field out of it.
|
|
171
|
+
* start runs on this machine. What it replaces is the alternative, which was telling people to
|
|
172
|
+
* open `~/.openagent.json` and copy a field out of it.
|
|
174
173
|
*/
|
|
175
174
|
export declare function onBridgeToken(): Promise<string | null>;
|
|
176
175
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Run a run-scoped RPC locally, or relay it to the
|
|
3
|
-
* relaying to a
|
|
2
|
+
* Run a run-scoped RPC locally, or relay it to the machine when `agentId` names an agent this daemon is
|
|
3
|
+
* relaying to a saved one (#1067 slice 2). For an ordinary local agent the remote lookup is empty and
|
|
4
4
|
* `local()` runs unchanged. For a remote agent there is no local checkout, so the call is forwarded to the
|
|
5
|
-
*
|
|
5
|
+
* machine with this computer's key there; if the machine is unreachable, or no longer lets this computer in, `unreachable` is returned - the same empty/error
|
|
6
6
|
* shape `local()` gives on a failed read - so the caller never special-cases a remote agent.
|
|
7
7
|
*/
|
|
8
8
|
export declare function relayOr<T>(agentId: string | undefined, fn: string, args: unknown[], local: () => Promise<T>, unreachable: T): Promise<T>;
|
|
@@ -102,11 +102,12 @@ export type OpenAgentEvent = {
|
|
|
102
102
|
event: DriverEvent;
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
|
-
* A live screen something the agent ran is showing:
|
|
106
|
-
*
|
|
105
|
+
* A live screen something the agent ran is showing: where it answers, on the loopback of the
|
|
106
|
+
* computer the run is on, live while it is the newest open screen at that address and the run
|
|
107
107
|
* has not ended. `label` names what it showed then. The same address with `ended` says the
|
|
108
108
|
* screen has gone. A diary line a command appends itself (agent-driver's `DIARY_ENV`);
|
|
109
|
-
* OpenAgent
|
|
109
|
+
* OpenAgent passes a watcher's calls on to the address (dashboard/screen.ts) and knows nothing
|
|
110
|
+
* of what the screen is.
|
|
110
111
|
*/
|
|
111
112
|
| {
|
|
112
113
|
kind: 'screen';
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loopback-address helpers,
|
|
3
|
-
* token, #1051) and the RPC mount (rejecting a rebound `Host`). A leaf module on purpose:
|
|
4
|
-
* `daemon.ts` imports the dashboard, so the mount cannot import these back out of it.
|
|
2
|
+
* Loopback-address helpers, for the RPC mount (rejecting a cross-origin page and a rebound `Host`).
|
|
5
3
|
*/
|
|
6
4
|
/**
|
|
7
|
-
* True when `host` is a loopback address the browser reaches without leaving the machine
|
|
8
|
-
* A bind-all (`0.0.0.0`, `::`) or a routable address is not
|
|
5
|
+
* True when `host` is a loopback address the browser reaches without leaving the machine.
|
|
6
|
+
* A bind-all (`0.0.0.0`, `::`) or a routable address is not.
|
|
9
7
|
*
|
|
10
8
|
* The IPv4 check matches the whole `127.0.0.0/8` range but only as an address: a bare
|
|
11
9
|
* `startsWith('127.')` also accepts a *registrable name* like `127.evil.com`, which is exactly the
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the link another computer's OpenAgent gives for a new device (its Settings, Devices, Add
|
|
3
|
+
* device): where this computer is let in, and the code that lets it in once. The code rides the
|
|
4
|
+
* link after the `#`. A server's link carries one thing more after the code and a dot: what the
|
|
5
|
+
* server's key is known by. Not a web address is `null`, and so is a link with no code.
|
|
6
|
+
*
|
|
7
|
+
* A leaf with no Node in it: the dashboard reads a paste with it as the person types, and the
|
|
8
|
+
* daemon reads it again before it asks to be let in.
|
|
9
|
+
*/
|
|
10
|
+
export interface MachineLink {
|
|
11
|
+
/** Where the other OpenAgent answers, as an origin (`http://studio.local:4201`). */
|
|
12
|
+
url: string;
|
|
13
|
+
/** Where this computer asks to be let in, and later takes itself out: the link without its code. */
|
|
14
|
+
door: string;
|
|
15
|
+
/** The code, good once. */
|
|
16
|
+
code: string;
|
|
17
|
+
/** What the machine's key is known by, when the link says: a call then goes only to a machine that shows that key. */
|
|
18
|
+
pin?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function parseMachineLink(pasted: string): MachineLink | null;
|
|
@@ -19,6 +19,8 @@ export type DialogRun = {
|
|
|
19
19
|
};
|
|
20
20
|
/** Injectable seam so tests never open a real dialog. */
|
|
21
21
|
export type DialogRunner = (command: string, args: string[]) => Promise<DialogRun>;
|
|
22
|
+
/** Whether this computer has a screen a folder dialog can open on: asked before one is offered. */
|
|
23
|
+
export declare function canPickDirectory(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): boolean;
|
|
22
24
|
/**
|
|
23
25
|
* Open the OS folder picker and wait for the user's choice.
|
|
24
26
|
*
|
|
@@ -4,7 +4,8 @@ import { type PackageCommandResult } from '@openagt/agent-data';
|
|
|
4
4
|
* `exports["./dashboard"]`, and optionally its server part, named by `exports["./server"]`.
|
|
5
5
|
* Any dependency of the project that exports `./dashboard` is a module, whoever wrote it, and the
|
|
6
6
|
* packages OpenAgent brings itself come the same way, for the projects that have them
|
|
7
|
-
* (`built-in.ts`).
|
|
7
|
+
* (`built-in.ts`). A package that is this computer's is a module of no project: see
|
|
8
|
+
* {@link readComputerModules}.
|
|
8
9
|
*/
|
|
9
10
|
export interface ProjectModule {
|
|
10
11
|
/** The package's name. */
|
|
@@ -15,7 +16,7 @@ export interface ProjectModule {
|
|
|
15
16
|
dir: string;
|
|
16
17
|
/** The module's browser part's file name inside {@link dir}. */
|
|
17
18
|
entry: string;
|
|
18
|
-
/** The package's commands, by name, as absolute paths: what the module may run in this project. */
|
|
19
|
+
/** The package's commands, by name, as absolute paths: what the module may run, in this project or, for one of the computer's, in none. */
|
|
19
20
|
bins: Record<string, string>;
|
|
20
21
|
/** The module's server part, an absolute path inside the package, when it has one. */
|
|
21
22
|
server?: string;
|
|
@@ -29,6 +30,13 @@ export interface ProjectModule {
|
|
|
29
30
|
export declare function readProjectModules(root: string): Promise<ProjectModule[]>;
|
|
30
31
|
/** The one module of this project that `name` names, or undefined. */
|
|
31
32
|
export declare function findProjectModule(root: string, name: string): Promise<ProjectModule | undefined>;
|
|
33
|
+
/**
|
|
34
|
+
* The modules that are this computer's and no project's: the ones among the packages OpenAgent
|
|
35
|
+
* brings for the computer (`built-in.ts`). They are there with no project added. Sorted by name.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readComputerModules(): Promise<ProjectModule[]>;
|
|
38
|
+
/** The one module of this computer's that `name` names, or undefined. */
|
|
39
|
+
export declare function findComputerModule(name: string): Promise<ProjectModule | undefined>;
|
|
32
40
|
/**
|
|
33
41
|
* The file a module serves at `rel`, a path relative to its module's directory: its module, its
|
|
34
42
|
* stylesheet, a chunk. `undefined` for a path that leaves that directory (symlinks resolved) or
|
|
@@ -43,7 +51,8 @@ export type ModuleCommandResult = PackageCommandResult;
|
|
|
43
51
|
* (`npx @openagt/skill-logs@0.1`), so the module and the agent see the same thing and OpenAgent knows neither.
|
|
44
52
|
*
|
|
45
53
|
* `command` picks one of the package's commands; a package with exactly one needs none. The
|
|
46
|
-
* command runs with Node (a package's commands are Node scripts), in the project
|
|
54
|
+
* command runs with Node (a package's commands are Node scripts), in `root` (the project's, or
|
|
55
|
+
* the person's home folder for a module of the computer's), never
|
|
47
56
|
* through a shell, bounded in time and output. Refused: a command the package does not have, too
|
|
48
57
|
* many or too long arguments. A command that exits non-zero answers its last stderr line; one that
|
|
49
58
|
* prints no JSON says so.
|
|
@@ -3,8 +3,9 @@ import { type PublishPick } from './publish-levels.js';
|
|
|
3
3
|
* The multi-project registry (#390): the list of projects the user has
|
|
4
4
|
* installed OpenAgent into, kept as a single JSON file `.bashrc`-style —
|
|
5
5
|
* `$HOME/.openagent.json` — so it is the user's responsibility to re-create
|
|
6
|
-
* per machine. The same file also holds the user's dashboard preferences (#410)
|
|
7
|
-
* so the daemon owns one user file and the UI never
|
|
6
|
+
* per machine. The same file also holds the user's dashboard preferences (#410)
|
|
7
|
+
* and the machines they saved, so the daemon owns one user file and the UI never
|
|
8
|
+
* needs localStorage.
|
|
8
9
|
*/
|
|
9
10
|
/** One registered project. */
|
|
10
11
|
export interface ProjectRecord {
|
|
@@ -15,6 +16,25 @@ export interface ProjectRecord {
|
|
|
15
16
|
/** ISO timestamp the project was added. */
|
|
16
17
|
addedAt: string;
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* A saved machine: another computer running OpenAgent that a run can be sent to. Kept in this
|
|
21
|
+
* file, the person's own, so every browser on this computer shows the same machines and the
|
|
22
|
+
* key that reaches one never leaves the two machines.
|
|
23
|
+
*/
|
|
24
|
+
export interface MachineRecord {
|
|
25
|
+
/** The machine's address, which is also what names it: saving the same address again replaces it. */
|
|
26
|
+
id: string;
|
|
27
|
+
/** The name the person gave it, or its host when they gave none. */
|
|
28
|
+
label: string;
|
|
29
|
+
/** Where its OpenAgent answers, as an origin (`http://studio.local:4201`). */
|
|
30
|
+
url: string;
|
|
31
|
+
/** This computer's own key on that machine. Never handed to a browser. */
|
|
32
|
+
key: string;
|
|
33
|
+
/** Where this computer was let in there, and where it takes itself out when the machine is removed. */
|
|
34
|
+
door: string;
|
|
35
|
+
/** What the machine's key is known by, when its link said: every call goes only to a machine that shows that key. */
|
|
36
|
+
pin?: string;
|
|
37
|
+
}
|
|
18
38
|
/**
|
|
19
39
|
* The dashboard's Global options (#410), persisted next to the project list so they
|
|
20
40
|
* survive restarts without localStorage — the daemon reads/writes them, the SPA reads
|
|
@@ -104,11 +124,16 @@ export interface Registry {
|
|
|
104
124
|
projects: ProjectRecord[];
|
|
105
125
|
preferences: Preferences;
|
|
106
126
|
/**
|
|
107
|
-
* The
|
|
108
|
-
* A top-level field, deliberately not a {@link Preferences} one, so it is never shipped
|
|
109
|
-
* browser bundle. Absent on a
|
|
127
|
+
* The browser bridge's key (#1237): generated when the bridge is first switched on and reused
|
|
128
|
+
* after. A top-level field, deliberately not a {@link Preferences} one, so it is never shipped
|
|
129
|
+
* to the browser bundle. Absent on a machine that never had the bridge on.
|
|
110
130
|
*/
|
|
111
|
-
|
|
131
|
+
bridgeToken?: string;
|
|
132
|
+
/**
|
|
133
|
+
* The saved machines. Top-level like {@link bridgeToken}, and for the same reason: each one
|
|
134
|
+
* carries a key, so the list is never part of what the browser is handed.
|
|
135
|
+
*/
|
|
136
|
+
machines?: MachineRecord[];
|
|
112
137
|
}
|
|
113
138
|
/** A read/write handle for the user preferences, wired into the dashboard's context by the daemon. */
|
|
114
139
|
export interface PreferencesStore {
|
|
@@ -122,7 +147,7 @@ export interface PreferencesStore {
|
|
|
122
147
|
}
|
|
123
148
|
/** The registry file name: a single file under `$XDG_CONFIG_HOME` (dotted under `$HOME`). */
|
|
124
149
|
export declare const REGISTRY_FILE = "openagent.json";
|
|
125
|
-
/** Owner read/write only: the file holds the
|
|
150
|
+
/** Owner read/write only: the file holds the bridge's key and the saved machines' keys. */
|
|
126
151
|
export declare const REGISTRY_FILE_MODE = 384;
|
|
127
152
|
/**
|
|
128
153
|
* Deterministic, URL-safe id for a project path: the sanitized basename plus a
|
|
@@ -151,7 +176,7 @@ export interface RegistryFs {
|
|
|
151
176
|
rename?(from: string, to: string): Promise<void>;
|
|
152
177
|
/**
|
|
153
178
|
* Narrow a file's permissions. Optional, and best-effort at the call site: this file holds the
|
|
154
|
-
*
|
|
179
|
+
* bridge's key and the saved machines' keys, so it is written owner-only — but a
|
|
155
180
|
* filesystem that cannot express that (Windows, a FAT volume) must not fail the write.
|
|
156
181
|
*/
|
|
157
182
|
chmod?(path: string, mode: number): Promise<void>;
|
|
@@ -205,15 +230,33 @@ export declare function writePreferences(preferences: Preferences, fs?: Registry
|
|
|
205
230
|
*/
|
|
206
231
|
export declare function patchPreferences(patch: Preferences, fs?: RegistryFs, env?: NodeJS.ProcessEnv): Promise<Preferences>;
|
|
207
232
|
/**
|
|
208
|
-
* The
|
|
209
|
-
* only
|
|
210
|
-
* other mutators so two concurrent
|
|
211
|
-
|
|
233
|
+
* The browser bridge's key (#1237): read the persisted one, or generate + persist it now. Called
|
|
234
|
+
* only with the bridge switched on, so a machine that never had it on never grows one. Serialized
|
|
235
|
+
* with the other mutators so two concurrent starts can't each write a different key.
|
|
236
|
+
*/
|
|
237
|
+
export declare function ensureBridgeToken(fs?: RegistryFs, env?: NodeJS.ProcessEnv): Promise<string>;
|
|
238
|
+
/** The persisted bridge key, or `undefined` when none exists. A pure read: it never generates one. */
|
|
239
|
+
export declare function readBridgeToken(fs?: RegistryFs, env?: NodeJS.ProcessEnv): Promise<string | undefined>;
|
|
240
|
+
/** The saved machines, newest first. Forgiving like every read of this file: none on a bad file. */
|
|
241
|
+
export declare function listMachines(fs?: RegistryFs, env?: NodeJS.ProcessEnv): Promise<MachineRecord[]>;
|
|
242
|
+
/**
|
|
243
|
+
* Save a machine, newest first. One per address: saving an address again replaces its name and
|
|
244
|
+
* its key, which is how a machine whose key changed is fixed. Answers the stored record, and the
|
|
245
|
+
* records it took the place of (the one saved at that address before, the oldest past the cap):
|
|
246
|
+
* each still holds a key the caller takes out of its machine.
|
|
212
247
|
*/
|
|
213
|
-
export declare function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
248
|
+
export declare function addMachine(machine: {
|
|
249
|
+
url: string;
|
|
250
|
+
key: string;
|
|
251
|
+
door: string;
|
|
252
|
+
pin?: string;
|
|
253
|
+
label?: string;
|
|
254
|
+
}, fs?: RegistryFs, env?: NodeJS.ProcessEnv): Promise<{
|
|
255
|
+
record: MachineRecord;
|
|
256
|
+
displaced: MachineRecord[];
|
|
257
|
+
}>;
|
|
258
|
+
/** Take a saved machine off the list, by id. Answers the one that was there. */
|
|
259
|
+
export declare function removeMachine(id: string, fs?: RegistryFs, env?: NodeJS.ProcessEnv): Promise<MachineRecord | undefined>;
|
|
217
260
|
/** A {@link PreferencesStore} bound to the real registry file, wired by the daemon so the
|
|
218
261
|
* dashboard's preferences RPCs read/write the user's home file.
|
|
219
262
|
*
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type GitRunner } from '@openagt/agent-data';
|
|
2
|
+
/**
|
|
3
|
+
* The one name a project has on every machine: where its repository was cloned from, as
|
|
4
|
+
* `host/path` (`github.com/me/shop`). A project's id is made from its folder's path, which is
|
|
5
|
+
* another path on another machine, so a run sent to a machine names its project by this.
|
|
6
|
+
*
|
|
7
|
+
* The same repository reads the same whichever way it was cloned: the scheme, a user before the
|
|
8
|
+
* host, a port, a trailing `.git` or slash are dropped, and letters are lowered, since the git
|
|
9
|
+
* hosts match names without regard to case. Not an address at all (a path on this disk, a
|
|
10
|
+
* `file:` address) is none.
|
|
11
|
+
*
|
|
12
|
+
* What it does not see through: a host that serves the two ways under two names or two paths
|
|
13
|
+
* (`ssh.github.com`, Azure DevOps). Such a project reads as two, and the other machine says it
|
|
14
|
+
* does not have it.
|
|
15
|
+
*/
|
|
16
|
+
export declare function addressOfRemote(remote: string): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* The address of the repository at `cwd`: its `origin` remote, the one every push goes to. A
|
|
19
|
+
* project with no `origin`, or one that is a folder on this disk, has none and runs on this
|
|
20
|
+
* machine only.
|
|
21
|
+
*/
|
|
22
|
+
export declare function repositoryAddress(cwd: string, git?: GitRunner): Promise<string | undefined>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OpenAgentEvent } from './events.js';
|
|
2
|
+
/**
|
|
3
|
+
* Which of a run's `screen` lines are live and which are hidden. Live: the newest line at its
|
|
4
|
+
* address with no `ended` line for it after, and no run `end` after it other than one waiting on
|
|
5
|
+
* an answer. Every `ended` line is hidden: the screen going is said by its line no longer being
|
|
6
|
+
* live.
|
|
7
|
+
*/
|
|
8
|
+
export declare function foldScreenRows(events: readonly OpenAgentEvent[]): {
|
|
9
|
+
live: Set<OpenAgentEvent>;
|
|
10
|
+
hidden: Set<OpenAgentEvent>;
|
|
11
|
+
};
|
|
12
|
+
/** Where a run's live screen answers: the address of its newest live `screen` line, or nothing. */
|
|
13
|
+
export declare function liveScreen(events: readonly OpenAgentEvent[]): string | undefined;
|
|
@@ -157,12 +157,12 @@ export interface AgentMeta {
|
|
|
157
157
|
browserStreamPort?: number;
|
|
158
158
|
/**
|
|
159
159
|
* Where this run executes (#1050/#1053/#610): `actions` for a GitHub Actions run, `web` for a
|
|
160
|
-
* Claude Code cloud session, `remote` when relayed to a
|
|
160
|
+
* Claude Code cloud session, `remote` when relayed to a saved machine (#1067), absent for a
|
|
161
161
|
* local run. Persisted so the agent view can tell a burst-mode Actions run from a stalled live
|
|
162
162
|
* feed, show a cloud agent's session link after a reload, and gate the browser pane off (#1053).
|
|
163
163
|
*/
|
|
164
164
|
target?: 'local' | 'actions' | 'remote' | 'web';
|
|
165
|
-
/** The
|
|
165
|
+
/** The saved machine a remote agent (#1067) executes on, for the session list + notice after a reload. */
|
|
166
166
|
remoteLabel?: string;
|
|
167
167
|
/**
|
|
168
168
|
* The flow this agent started under (#1467): `build` for the scope→build orchestration, `prompt`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function openagentVersion(): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
import type { ProvidedCommand } from '@openagt/agent-data';
|
|
3
|
+
/**
|
|
4
|
+
* The services of OpenAgent's own packages: each declared command's `serve`, run as a process of
|
|
5
|
+
* its own for as long as OpenAgent runs, and told where OpenAgent is (`OPENAGENT_URL`). OpenAgent
|
|
6
|
+
* knows nothing of what a service does. One that ends by itself is started again after a
|
|
7
|
+
* while; all of them end with OpenAgent. Each is started in a process group of its own, so a
|
|
8
|
+
* Ctrl-C in OpenAgent's terminal reaches OpenAgent alone, which then ends them in its own order.
|
|
9
|
+
*/
|
|
10
|
+
export interface PackageServicesOptions {
|
|
11
|
+
/** The commands to run, each a package's declared service. */
|
|
12
|
+
commands: readonly ProvidedCommand[];
|
|
13
|
+
/** OpenAgent's own address on this computer. */
|
|
14
|
+
url: string;
|
|
15
|
+
env: NodeJS.ProcessEnv;
|
|
16
|
+
log: (line: string) => void;
|
|
17
|
+
/** How a service's process is started; the real one when unsaid. */
|
|
18
|
+
spawn?: (bin: string, env: NodeJS.ProcessEnv) => ChildProcess;
|
|
19
|
+
/** After how long a service that ended by itself is started again. */
|
|
20
|
+
restartMs?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface PackageServices {
|
|
23
|
+
/** End every service, and wait until each is gone. */
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function startPackageServices(opts: PackageServicesOptions): PackageServices;
|
|
27
|
+
//# sourceMappingURL=package-services.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-services.d.ts","sourceRoot":"","sources":["../src/package-services.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D;;;;;;GAMG;AAEH,MAAM,WAAW,sBAAsB;IACrC,8DAA8D;IAC9D,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;IACpC,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,oEAAoE;IACpE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,YAAY,CAAA;IAC7D,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAKD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,sBAAsB,GAAG,eAAe,CAwDlF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
2
|
+
/** How long a service gets to end by itself once asked, before it is killed. */
|
|
3
|
+
const STOP_GRACE_MS = 3_000;
|
|
4
|
+
export function startPackageServices(opts) {
|
|
5
|
+
const spawn = opts.spawn ?? ((bin, env) => nodeSpawn(process.execPath, [bin, 'serve'], { env, stdio: ['ignore', 'ignore', 'pipe'], detached: true }));
|
|
6
|
+
const env = { ...opts.env, OPENAGENT_URL: opts.url };
|
|
7
|
+
let stopping = false;
|
|
8
|
+
const running = new Map();
|
|
9
|
+
const timers = new Set();
|
|
10
|
+
const start = (command) => {
|
|
11
|
+
if (stopping)
|
|
12
|
+
return;
|
|
13
|
+
const child = spawn(command.bin, env);
|
|
14
|
+
running.set(command.package, child);
|
|
15
|
+
child.stderr?.setEncoding('utf8').on('data', (said) => {
|
|
16
|
+
for (const line of said.split('\n'))
|
|
17
|
+
if (line.trim())
|
|
18
|
+
opts.log(line.trim());
|
|
19
|
+
});
|
|
20
|
+
const ended = (why) => {
|
|
21
|
+
if (running.get(command.package) !== child)
|
|
22
|
+
return;
|
|
23
|
+
running.delete(command.package);
|
|
24
|
+
if (stopping)
|
|
25
|
+
return;
|
|
26
|
+
opts.log(`${command.package}: its service ended (${why}); it is started again shortly`);
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
timers.delete(timer);
|
|
29
|
+
start(command);
|
|
30
|
+
}, opts.restartMs ?? 5_000);
|
|
31
|
+
timers.add(timer);
|
|
32
|
+
};
|
|
33
|
+
child.once('error', err => ended(err.message));
|
|
34
|
+
child.once('exit', (code, signal) => ended(signal ?? `exit ${code}`));
|
|
35
|
+
};
|
|
36
|
+
for (const command of opts.commands)
|
|
37
|
+
start(command);
|
|
38
|
+
return {
|
|
39
|
+
async stop() {
|
|
40
|
+
stopping = true;
|
|
41
|
+
for (const timer of timers)
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
timers.clear();
|
|
44
|
+
await Promise.all([...running.values()].map(child => new Promise(resolve => {
|
|
45
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
46
|
+
return resolve();
|
|
47
|
+
const kill = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);
|
|
48
|
+
child.once('exit', () => {
|
|
49
|
+
clearTimeout(kill);
|
|
50
|
+
resolve();
|
|
51
|
+
});
|
|
52
|
+
child.once('error', () => {
|
|
53
|
+
clearTimeout(kill);
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
child.kill('SIGTERM');
|
|
57
|
+
})));
|
|
58
|
+
running.clear();
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=package-services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-services.js","sourceRoot":"","sources":["../src/package-services.ts"],"names":[],"mappings":"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"}
|
package/dist/pick-directory.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export type DialogRun = {
|
|
|
19
19
|
};
|
|
20
20
|
/** Injectable seam so tests never open a real dialog. */
|
|
21
21
|
export type DialogRunner = (command: string, args: string[]) => Promise<DialogRun>;
|
|
22
|
+
/** Whether this computer has a screen a folder dialog can open on: asked before one is offered. */
|
|
23
|
+
export declare function canPickDirectory(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): boolean;
|
|
22
24
|
/**
|
|
23
25
|
* Open the OS folder picker and wait for the user's choice.
|
|
24
26
|
*
|