@agent-workshop/adoc-core 0.1.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.
Files changed (64) hide show
  1. package/LICENSE +5 -0
  2. package/THIRD_PARTY_NOTICES.md +49 -0
  3. package/dist/claim.d.ts +17 -0
  4. package/dist/claim.js +35 -0
  5. package/dist/claim.js.map +1 -0
  6. package/dist/client.d.ts +14 -0
  7. package/dist/client.js +49 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/config.d.ts +39 -0
  10. package/dist/config.js +110 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/errors.d.ts +6 -0
  13. package/dist/errors.js +13 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/fetch.d.ts +19 -0
  16. package/dist/fetch.js +106 -0
  17. package/dist/fetch.js.map +1 -0
  18. package/dist/git.d.ts +1 -0
  19. package/dist/git.js +13 -0
  20. package/dist/git.js.map +1 -0
  21. package/dist/herdr.d.ts +44 -0
  22. package/dist/herdr.js +134 -0
  23. package/dist/herdr.js.map +1 -0
  24. package/dist/home.d.ts +12 -0
  25. package/dist/home.js +43 -0
  26. package/dist/home.js.map +1 -0
  27. package/dist/index.d.ts +18 -0
  28. package/dist/index.js +19 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/messages.d.ts +76 -0
  31. package/dist/messages.js +119 -0
  32. package/dist/messages.js.map +1 -0
  33. package/dist/names.d.ts +14 -0
  34. package/dist/names.js +19 -0
  35. package/dist/names.js.map +1 -0
  36. package/dist/plugins.d.ts +43 -0
  37. package/dist/plugins.js +157 -0
  38. package/dist/plugins.js.map +1 -0
  39. package/dist/registry.d.ts +11 -0
  40. package/dist/registry.js +39 -0
  41. package/dist/registry.js.map +1 -0
  42. package/dist/report.d.ts +3 -0
  43. package/dist/report.js +9 -0
  44. package/dist/report.js.map +1 -0
  45. package/dist/scan.d.ts +35 -0
  46. package/dist/scan.js +163 -0
  47. package/dist/scan.js.map +1 -0
  48. package/dist/server.d.ts +80 -0
  49. package/dist/server.js +576 -0
  50. package/dist/server.js.map +1 -0
  51. package/dist/skills.d.ts +46 -0
  52. package/dist/skills.js +131 -0
  53. package/dist/skills.js.map +1 -0
  54. package/dist/terminal.d.ts +28 -0
  55. package/dist/terminal.js +110 -0
  56. package/dist/terminal.js.map +1 -0
  57. package/dist/transports.d.ts +21 -0
  58. package/dist/transports.js +69 -0
  59. package/dist/transports.js.map +1 -0
  60. package/dist/workspace.d.ts +182 -0
  61. package/dist/workspace.js +392 -0
  62. package/dist/workspace.js.map +1 -0
  63. package/package.json +54 -0
  64. package/skill/SKILL.md +219 -0
package/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright (C) 2026 adoc contributors
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,49 @@
1
+ # Third-party notices
2
+
3
+ adoc's original code and documentation use the Zero-Clause BSD License (0BSD). That license does not replace the
4
+ licenses of third-party components, and no third-party component is relicensed by this repository.
5
+
6
+ ## Browser distributions
7
+
8
+ Two packages carry bundled browser code:
9
+
10
+ - `@agent-workshop/adoc-webapp`: the web UI in `dist/`. Its build records the packages actually bundled in
11
+ `dist/licenses/packages.json` and copies their upstream LICENSE, COPYING, COPYRIGHT and NOTICE files beneath
12
+ `dist/licenses/`.
13
+ - `@agent-workshop/adoc-plugin-sketch`: the drawing board in `client/`, with its inventory and license files in
14
+ `client/licenses/`.
15
+
16
+ Keep these files when redistributing the built browser assets.
17
+
18
+ The main browser dependencies are React, React DOM, React Router, Mermaid (with KaTeX), xterm.js and Lucide in the web
19
+ UI, and Excalidraw with React and Radix UI in the drawing board. Most use MIT, ISC, BSD or Apache-2.0.
20
+
21
+ - DOMPurify offers MPL-2.0 OR Apache-2.0; adoc uses the Apache-2.0 option.
22
+ - Some packages are published without a license file although their manifest names one: Excalidraw, the Radix UI
23
+ primitives, react-remove-scroll-bar and fastdom (all MIT). The build includes the upstream texts kept in
24
+ `tooling/licenses/`.
25
+
26
+ ### Eclipse Layout Kernel / elkjs
27
+
28
+ Mermaid bundles elkjs, a separately licensed layout engine, which adoc uses under EPL-2.0 without modifying it. Its
29
+ license is included in the generated license inventory. Corresponding source is available from:
30
+
31
+ - https://github.com/kieler/elkjs (select the release matching the inventory version)
32
+ - https://github.com/eclipse/elk (the underlying Eclipse Layout Kernel)
33
+ - https://www.eclipse.org/legal/epl-2.0/
34
+
35
+ Recipients may obtain, modify and redistribute the EPL-covered source under EPL-2.0. adoc's 0BSD license applies to its
36
+ independent code, not to ELK.
37
+
38
+ ## Fonts
39
+
40
+ - The web UI serves Pretendard, D2Coding (both SIL Open Font License 1.1) and Symbols Nerd Font Mono; their license
41
+ files are next to them in `dist/assets/fonts/`.
42
+ - The drawing board serves the fonts that Excalidraw ships in `client/fonts/` (Excalifont, Virgil, Nunito, Lilita One,
43
+ Comic Shanns, Cascadia Code, Liberation Sans, Assistant and Xiaolai); they are distributed under the terms that
44
+ Excalidraw states for them in https://github.com/excalidraw/excalidraw.
45
+
46
+ ## Installed runtime dependencies
47
+
48
+ The packages that npm installs next to adoc, such as the MCP SDK, ws, yaml, zod, semver, commander, markdown-it and
49
+ highlight.js, are not bundled: each keeps its own license in its own package.
@@ -0,0 +1,17 @@
1
+ import type { AdocHome } from './home.js';
2
+ import type { ResolvedPane } from './herdr.js';
3
+ export declare const CLAIM_FILE = "claim.yaml";
4
+ /** _Agent_Claim_: the herdr pane where the _Assigned_Agent_ runs, kept in `.adoc/claim.yaml`. */
5
+ export interface AgentClaim {
6
+ herdrSession: string;
7
+ socket: string;
8
+ pane: string;
9
+ terminal: string;
10
+ agent?: string;
11
+ agentSession?: string;
12
+ claimedAt: string;
13
+ }
14
+ export declare function claimPath(home: AdocHome): string;
15
+ export declare function readClaim(home: AdocHome): Promise<AgentClaim | undefined>;
16
+ export declare function writeClaim(home: AdocHome, resolved: ResolvedPane): Promise<AgentClaim>;
17
+ export declare function removeClaim(home: AdocHome): Promise<void>;
package/dist/claim.js ADDED
@@ -0,0 +1,35 @@
1
+ import { readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { parse, stringify } from 'yaml';
4
+ export const CLAIM_FILE = 'claim.yaml';
5
+ export function claimPath(home) {
6
+ return join(home.home, CLAIM_FILE);
7
+ }
8
+ export async function readClaim(home) {
9
+ try {
10
+ const value = parse(await readFile(claimPath(home), 'utf8'));
11
+ return value && typeof value.pane === 'string' && typeof value.socket === 'string' ? value : undefined;
12
+ }
13
+ catch {
14
+ return undefined;
15
+ }
16
+ }
17
+ export async function writeClaim(home, resolved) {
18
+ const claim = {
19
+ herdrSession: resolved.herdrSession,
20
+ socket: resolved.socket,
21
+ pane: resolved.pane.pane_id,
22
+ terminal: resolved.pane.terminal_id,
23
+ claimedAt: new Date().toISOString(),
24
+ };
25
+ if (resolved.pane.agent)
26
+ claim.agent = resolved.pane.agent;
27
+ if (resolved.pane.agent_session?.value)
28
+ claim.agentSession = resolved.pane.agent_session.value;
29
+ await writeFile(claimPath(home), `# The herdr pane of the assigned agent on this computer. Written by adoc agent claim; do not commit.\n${stringify(claim)}`);
30
+ return claim;
31
+ }
32
+ export async function removeClaim(home) {
33
+ await rm(claimPath(home), { force: true });
34
+ }
35
+ //# sourceMappingURL=claim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.js","sourceRoot":"","sources":["../src/claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAIxC,MAAM,CAAC,MAAM,UAAU,GAAG,YAAY,CAAC;AAavC,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC5C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAsB,CAAC;QAClF,OAAO,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACzG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAc,EAAE,QAAsB;IACrE,MAAM,KAAK,GAAe;QACxB,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO;QAC3B,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK;QAAE,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;IAC3D,IAAI,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK;QAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;IAC/F,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,yGAAyG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9J,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAc;IAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { AdocConfig } from './config.js';
2
+ /** Talks to the running _Adoc_Server_ of a workspace from the command line. */
3
+ export declare class ServerClient {
4
+ readonly url: string;
5
+ private readonly workspace;
6
+ private constructor();
7
+ /** Finds the server through its _Server_Record_, falling back to the address in adoc.yaml. */
8
+ static find(config: AdocConfig, workspace: string): Promise<ServerClient>;
9
+ /** Fails with a clear error unless the server of this workspace answers. */
10
+ ensure(): Promise<void>;
11
+ get<T>(path: string): Promise<T>;
12
+ post<T>(path: string, body: unknown): Promise<T>;
13
+ private request;
14
+ }
package/dist/client.js ADDED
@@ -0,0 +1,49 @@
1
+ import { AdocError, errorMessage } from './errors.js';
2
+ import { readServerRecord } from './registry.js';
3
+ import { PROTOCOL } from './server.js';
4
+ /** Talks to the running _Adoc_Server_ of a workspace from the command line. */
5
+ export class ServerClient {
6
+ url;
7
+ workspace;
8
+ constructor(url, workspace) {
9
+ this.url = url;
10
+ this.workspace = workspace;
11
+ }
12
+ /** Finds the server through its _Server_Record_, falling back to the address in adoc.yaml. */
13
+ static async find(config, workspace) {
14
+ const record = await readServerRecord(workspace);
15
+ if (record)
16
+ return new ServerClient(record.url, workspace);
17
+ const host = config.server.host === '0.0.0.0' || config.server.host === '::' ? '127.0.0.1' : config.server.host;
18
+ return new ServerClient(`http://${host}:${config.server.port}`, workspace);
19
+ }
20
+ /** Fails with a clear error unless the server of this workspace answers. */
21
+ async ensure() {
22
+ let health;
23
+ try {
24
+ const response = await fetch(`${this.url}/api/health`, { signal: AbortSignal.timeout(2000) });
25
+ health = (await response.json());
26
+ }
27
+ catch (error) {
28
+ throw new AdocError('server.unreachable', `No adoc server answers at ${this.url} (${errorMessage(error)}); start it with adoc server run.`);
29
+ }
30
+ if (health.protocol !== PROTOCOL)
31
+ throw new AdocError('server.protocol', `${this.url} is not an adoc server.`);
32
+ if (health.workspace !== this.workspace)
33
+ throw new AdocError('server.workspace', `The adoc server at ${this.url} serves ${health.workspace}, not ${this.workspace}.`);
34
+ }
35
+ async get(path) {
36
+ return this.request(path, {});
37
+ }
38
+ async post(path, body) {
39
+ return this.request(path, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });
40
+ }
41
+ async request(path, init) {
42
+ const response = await fetch(this.url + path, init);
43
+ const body = (await response.json());
44
+ if (!response.ok)
45
+ throw new AdocError('server.request', body.error ?? `${path} failed with ${response.status}`);
46
+ return body;
47
+ }
48
+ }
49
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ import type { AdocHome } from './home.js';
3
+ declare const transportSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4
+ kind: z.ZodLiteral<"herdr">;
5
+ }, z.core.$strip>, z.ZodObject<{
6
+ kind: z.ZodLiteral<"wait">;
7
+ }, z.core.$strip>], "kind">;
8
+ /** A _Plugin_ that the config declares: its key, its _Plugin_Source_ and the folder of the file that declares it. */
9
+ export interface DeclaredPlugin {
10
+ readonly key: string;
11
+ readonly source: string;
12
+ /** Relative paths and npm lookups of the source start here. */
13
+ readonly base: string;
14
+ }
15
+ /** The _Adoc_Config_ laid over the _User_Config_. */
16
+ export interface AdocConfig {
17
+ /** In tab order: `ui.tabs` first, then the order of declaration. */
18
+ readonly plugins: readonly DeclaredPlugin[];
19
+ /** Relative to the workspace root. */
20
+ readonly watch: readonly string[];
21
+ readonly agent: {
22
+ readonly name: string;
23
+ readonly transport: TransportConfig;
24
+ };
25
+ readonly server: {
26
+ readonly host: string;
27
+ readonly port: number;
28
+ };
29
+ readonly ui: {
30
+ readonly theme: 'dark' | 'light' | 'system';
31
+ };
32
+ }
33
+ export type TransportConfig = z.infer<typeof transportSchema>;
34
+ /** The _User_Config_: `adoc/adoc.yaml` in the XDG config directory. */
35
+ export declare function userConfigPath(env?: NodeJS.ProcessEnv): string;
36
+ /** Reads the _User_Config_ and the _Adoc_Config_, and lays the second over the first, setting by setting. */
37
+ export declare function readConfig(home: AdocHome, env?: NodeJS.ProcessEnv): Promise<AdocConfig>;
38
+ export declare const CONFIG_TEMPLATE = "# adoc workspace configuration, laid over ~/.config/adoc/adoc.yaml. Paths are relative to this file.\nplugins: # plugin key: npm:<package>, github:<owner>/<repo>/<folder>, a path such as ./plugins/x, or off\n NOTE: npm:@agent-workshop/adoc-plugin-note\n TODO: npm:@agent-workshop/adoc-plugin-todo\n SKETCH: npm:@agent-workshop/adoc-plugin-sketch\n TASK: npm:@agent-workshop/adoc-plugin-task\n KANBAN: npm:@agent-workshop/adoc-plugin-kanban\nwatch:\n - ../docs\nagent:\n name: agent\n transport:\n kind: herdr # herdr (the pane from adoc agent claim) | wait (the agent runs adoc message wait)\nserver:\n host: 127.0.0.1 # 0.0.0.0 to accept connections from the internal network (no authentication)\n port: 7700\nui:\n tabs: [NOTE, TODO, SKETCH, TASK, KANBAN]\n theme: dark # default colour scheme of the web UI: dark | light | system; each browser may choose another\n";
39
+ export {};
package/dist/config.js ADDED
@@ -0,0 +1,110 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join, relative, resolve } from 'node:path';
4
+ import { parse } from 'yaml';
5
+ import { z } from 'zod';
6
+ import { AdocError } from './errors.js';
7
+ import { PLUGIN_KEY_PATTERN } from './names.js';
8
+ const transportSchema = z.discriminatedUnion('kind', [
9
+ z.object({ kind: z.literal('herdr') }),
10
+ z.object({ kind: z.literal('wait') }),
11
+ ]);
12
+ /** One config file, the _Adoc_Config_ or the _User_Config_: every setting is optional, since the two are laid over each other. */
13
+ const fileSchema = z.object({
14
+ plugins: z.record(z.string().regex(PLUGIN_KEY_PATTERN, 'a plugin key must be uppercase letters A-Z only'), z.string().min(1)).optional(),
15
+ watch: z.array(z.string().min(1)).optional(),
16
+ agent: z.object({ name: z.string().min(1).optional(), transport: transportSchema.optional() }).optional(),
17
+ server: z.object({ host: z.string().optional(), port: z.number().int().min(1).max(65535).optional() }).optional(),
18
+ ui: z.object({ tabs: z.array(z.string()).optional(), theme: z.enum(['dark', 'light', 'system']).optional() }).optional(),
19
+ });
20
+ /** The _User_Config_: `adoc/adoc.yaml` in the XDG config directory. */
21
+ export function userConfigPath(env = process.env) {
22
+ return join(env.XDG_CONFIG_HOME || join(env.HOME || homedir(), '.config'), 'adoc', 'adoc.yaml');
23
+ }
24
+ const FORMAT_HINT = 'plugins:\n TODO: npm:@agent-workshop/adoc-plugin-todo\n TASK: ./plugins/task';
25
+ async function readFileConfig(path, required) {
26
+ let text;
27
+ try {
28
+ text = await readFile(path, 'utf8');
29
+ }
30
+ catch {
31
+ if (required)
32
+ throw new AdocError('config.missing', `Cannot read ${path}; run adoc init.`);
33
+ return {};
34
+ }
35
+ let raw;
36
+ try {
37
+ raw = parse(text) ?? {};
38
+ }
39
+ catch (error) {
40
+ throw new AdocError('config.invalid', `${path}: ${error.message}`);
41
+ }
42
+ if (Array.isArray(raw.plugins)) {
43
+ throw new AdocError('config.format', `${path}: plugins is a list in an earlier format; write it as a map from each plugin key to its source:\n${FORMAT_HINT}`);
44
+ }
45
+ const result = fileSchema.safeParse(raw);
46
+ if (!result.success) {
47
+ const details = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');
48
+ throw new AdocError('config.invalid', `${path}: ${details}`);
49
+ }
50
+ return result.data;
51
+ }
52
+ /** Reads the _User_Config_ and the _Adoc_Config_, and lays the second over the first, setting by setting. */
53
+ export async function readConfig(home, env = process.env) {
54
+ const userPath = userConfigPath(env);
55
+ const user = await readFileConfig(userPath, false);
56
+ const project = await readFileConfig(home.configPath, true);
57
+ const layers = [
58
+ { file: user, base: dirname(userPath) },
59
+ { file: project, base: home.home },
60
+ ];
61
+ const declared = new Map();
62
+ // The project's own plugins come before the ones only the user declares.
63
+ for (const { file, base } of [...layers].reverse()) {
64
+ for (const [key, source] of Object.entries(file.plugins ?? {}))
65
+ if (!declared.has(key))
66
+ declared.set(key, { key, source, base });
67
+ }
68
+ for (const [key, plugin] of declared)
69
+ if (plugin.source === 'off')
70
+ declared.delete(key);
71
+ const last = (pick) => {
72
+ for (const { file, base } of [...layers].reverse()) {
73
+ const value = pick(file);
74
+ if (value !== undefined)
75
+ return { value, base };
76
+ }
77
+ return undefined;
78
+ };
79
+ const tabs = last((f) => f.ui?.tabs)?.value ?? [];
80
+ const ordered = [...tabs.filter((key) => declared.has(key)), ...[...declared.keys()].filter((key) => !tabs.includes(key))];
81
+ const watch = last((f) => f.watch);
82
+ return {
83
+ plugins: ordered.map((key) => declared.get(key)),
84
+ watch: watch ? watch.value.map((path) => relative(home.workspace, resolve(watch.base, path)) || '.') : ['docs'],
85
+ agent: { name: last((f) => f.agent?.name)?.value ?? 'agent', transport: last((f) => f.agent?.transport)?.value ?? { kind: 'herdr' } },
86
+ server: { host: last((f) => f.server?.host)?.value ?? '127.0.0.1', port: last((f) => f.server?.port)?.value ?? 7700 },
87
+ ui: { theme: last((f) => f.ui?.theme)?.value ?? 'dark' },
88
+ };
89
+ }
90
+ export const CONFIG_TEMPLATE = `# adoc workspace configuration, laid over ~/.config/adoc/adoc.yaml. Paths are relative to this file.
91
+ plugins: # plugin key: npm:<package>, github:<owner>/<repo>/<folder>, a path such as ./plugins/x, or off
92
+ NOTE: npm:@agent-workshop/adoc-plugin-note
93
+ TODO: npm:@agent-workshop/adoc-plugin-todo
94
+ SKETCH: npm:@agent-workshop/adoc-plugin-sketch
95
+ TASK: npm:@agent-workshop/adoc-plugin-task
96
+ KANBAN: npm:@agent-workshop/adoc-plugin-kanban
97
+ watch:
98
+ - ../docs
99
+ agent:
100
+ name: agent
101
+ transport:
102
+ kind: herdr # herdr (the pane from adoc agent claim) | wait (the agent runs adoc message wait)
103
+ server:
104
+ host: 127.0.0.1 # 0.0.0.0 to accept connections from the internal network (no authentication)
105
+ port: 7700
106
+ ui:
107
+ tabs: [NOTE, TODO, SKETCH, TASK, KANBAN]
108
+ theme: dark # default colour scheme of the web UI: dark | light | system; each browser may choose another
109
+ `;
110
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** An expected failure with a stable code and a message meant for the user or agent reading it. */
2
+ export declare class AdocError extends Error {
3
+ readonly code: string;
4
+ constructor(code: string, message: string);
5
+ }
6
+ export declare function errorMessage(error: unknown): string;
package/dist/errors.js ADDED
@@ -0,0 +1,13 @@
1
+ /** An expected failure with a stable code and a message meant for the user or agent reading it. */
2
+ export class AdocError extends Error {
3
+ code;
4
+ constructor(code, message) {
5
+ super(message);
6
+ this.code = code;
7
+ this.name = 'AdocError';
8
+ }
9
+ }
10
+ export function errorMessage(error) {
11
+ return error instanceof Error ? error.message : String(error);
12
+ }
13
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,MAAM,OAAO,SAAU,SAAQ,KAAK;IAEvB,IAAI;IADf,YACW,IAAY,EACrB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;oBAHN,IAAI;QAIb,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { AdocConfig } from './config.js';
2
+ /** What happened to one GitHub _Plugin_Source_. */
3
+ export interface FetchOutcome {
4
+ readonly key: string;
5
+ readonly source: string;
6
+ readonly status: 'fetched' | 'present' | 'refused' | 'failed';
7
+ readonly commit?: string;
8
+ readonly reason?: string;
9
+ }
10
+ /** A hash of every file of a folder, by relative path and content, so that a changed fetched folder is noticed. */
11
+ export declare function folderHash(folder: string): Promise<string>;
12
+ /**
13
+ * Fetches the GitHub _Plugin_Source_ entries of the config into their _Plugin_Directory_: with `update` false only the
14
+ * ones not fetched yet, with `update` true again, refusing a folder whose files differ from what was fetched.
15
+ */
16
+ export declare function fetchGithubPlugins(config: AdocConfig, options: {
17
+ update: boolean;
18
+ keys?: readonly string[];
19
+ }, env?: NodeJS.ProcessEnv): Promise<FetchOutcome[]>;
package/dist/fetch.js ADDED
@@ -0,0 +1,106 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { createHash } from 'node:crypto';
3
+ import { cp, mkdir, mkdtemp, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { join, relative } from 'node:path';
6
+ import { promisify } from 'node:util';
7
+ import { AdocError, errorMessage } from './errors.js';
8
+ import { fetchedFolder, parseGithubSource, pluginDirectory } from './plugins.js';
9
+ const run = promisify(execFile);
10
+ const LOCK_FILE = 'plugins-lock.json';
11
+ async function readLock(directory) {
12
+ try {
13
+ return JSON.parse(await readFile(join(directory, LOCK_FILE), 'utf8'));
14
+ }
15
+ catch {
16
+ return {};
17
+ }
18
+ }
19
+ async function writeLock(directory, lock) {
20
+ const sorted = Object.fromEntries(Object.entries(lock).sort(([a], [b]) => a.localeCompare(b)));
21
+ await writeFile(join(directory, LOCK_FILE), `${JSON.stringify(sorted, null, 2)}\n`);
22
+ }
23
+ async function exists(path) {
24
+ try {
25
+ await stat(path);
26
+ return true;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ /** A hash of every file of a folder, by relative path and content, so that a changed fetched folder is noticed. */
33
+ export async function folderHash(folder) {
34
+ const hash = createHash('sha256');
35
+ const walk = async (dir) => {
36
+ for (const entry of (await readdir(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
37
+ const path = join(dir, entry.name);
38
+ if (entry.isDirectory())
39
+ await walk(path);
40
+ else
41
+ hash.update(relative(folder, path)).update('\0').update(await readFile(path)).update('\0');
42
+ }
43
+ };
44
+ await walk(folder);
45
+ return hash.digest('hex');
46
+ }
47
+ /** Fetches the folder of a GitHub _Plugin_Source_ at its ref into `target`, and returns the commit. */
48
+ async function fetchInto(source, target, env) {
49
+ const github = parseGithubSource(source);
50
+ const url = `${env.ADOC_GITHUB_URL || 'https://github.com'}/${github.owner}/${github.repo}.git`;
51
+ const work = await mkdtemp(join(tmpdir(), 'adoc-fetch-'));
52
+ try {
53
+ await run('git', ['-C', work, 'init', '-q']);
54
+ await run('git', ['-C', work, 'fetch', '-q', '--depth', '1', url, github.ref ?? 'HEAD']);
55
+ await run('git', ['-C', work, 'checkout', '-q', 'FETCH_HEAD']);
56
+ const commit = (await run('git', ['-C', work, 'rev-parse', 'HEAD'])).stdout.trim();
57
+ const folder = join(work, github.folder);
58
+ if (!(await exists(join(folder, 'index.js'))) && !(await exists(join(folder, 'index.ts'))) && !(await exists(join(folder, 'index.mjs')))) {
59
+ throw new Error(`${github.folder || 'the repository root'} of ${github.owner}/${github.repo} has no index.ts or index.js`);
60
+ }
61
+ await rm(target, { recursive: true, force: true });
62
+ await mkdir(target, { recursive: true });
63
+ await cp(folder, target, { recursive: true, filter: (path) => !relative(folder, path).split(/[\\/]/).includes('.git') });
64
+ return commit;
65
+ }
66
+ finally {
67
+ await rm(work, { recursive: true, force: true });
68
+ }
69
+ }
70
+ /**
71
+ * Fetches the GitHub _Plugin_Source_ entries of the config into their _Plugin_Directory_: with `update` false only the
72
+ * ones not fetched yet, with `update` true again, refusing a folder whose files differ from what was fetched.
73
+ */
74
+ export async function fetchGithubPlugins(config, options, env = process.env) {
75
+ const github = config.plugins.filter((p) => parseGithubSource(p.source));
76
+ const unknown = options.keys?.filter((key) => !github.some((p) => p.key === key)) ?? [];
77
+ if (unknown.length)
78
+ throw new AdocError('plugin.unknown', `No GitHub plugin source is declared for ${unknown.join(', ')}.`);
79
+ const chosen = options.keys?.length ? github.filter((p) => options.keys.includes(p.key)) : github;
80
+ const outcomes = [];
81
+ for (const plugin of chosen)
82
+ outcomes.push(await fetchOne(plugin, options.update, env));
83
+ return outcomes;
84
+ }
85
+ async function fetchOne(plugin, update, env) {
86
+ const { key, source } = plugin;
87
+ const directory = pluginDirectory(plugin.base);
88
+ const target = fetchedFolder(plugin);
89
+ const name = key.toLowerCase();
90
+ const lock = await readLock(directory);
91
+ const present = await exists(target);
92
+ if (present && !update)
93
+ return { key, source, status: 'present', ...(lock[name] ? { commit: lock[name].commit } : {}) };
94
+ if (present && (!lock[name] || lock[name].hash !== (await folderHash(target)))) {
95
+ return { key, source, status: 'refused', reason: `${target} differs from what was fetched; copy it to another folder to change it, or remove it to fetch again` };
96
+ }
97
+ try {
98
+ const commit = await fetchInto(source, target, env);
99
+ await writeLock(directory, { ...(await readLock(directory)), [name]: { source, commit, hash: await folderHash(target) } });
100
+ return { key, source, status: 'fetched', commit };
101
+ }
102
+ catch (error) {
103
+ return { key, source, status: 'failed', reason: errorMessage(error) };
104
+ }
105
+ }
106
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"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"}
package/dist/git.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function isGitRepository(directory: string): Promise<boolean>;
package/dist/git.js ADDED
@@ -0,0 +1,13 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ const run = promisify(execFile);
4
+ export async function isGitRepository(directory) {
5
+ try {
6
+ const { stdout } = await run('git', ['rev-parse', '--is-inside-work-tree'], { cwd: directory });
7
+ return stdout.trim() === 'true';
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB;IACrD,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAChG,OAAO,MAAM,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,44 @@
1
+ /** One pane as herdr's `session.snapshot` reports it. */
2
+ export interface HerdrPane {
3
+ pane_id: string;
4
+ terminal_id: string;
5
+ agent?: string;
6
+ agent_status?: string;
7
+ agent_session?: {
8
+ agent?: string;
9
+ kind?: string;
10
+ value?: string;
11
+ };
12
+ }
13
+ /** Sends one request over a herdr session socket (NDJSON) and returns its result. */
14
+ export declare function herdrCall<T>(socketPath: string, method: string, params?: unknown): Promise<T>;
15
+ /**
16
+ * Subscribes to herdr events on a session socket; the connection stays open.
17
+ * Returns a function that closes the subscription.
18
+ */
19
+ export declare function herdrSubscribe(socketPath: string, subscriptions: unknown[], onEvent: (event: {
20
+ event?: string;
21
+ data?: unknown;
22
+ }) => void, onClose: () => void): () => void;
23
+ /** The socket of every herdr session on this computer, by session name. */
24
+ export declare function herdrSessions(home?: string): Promise<Array<{
25
+ name: string;
26
+ socket: string;
27
+ }>>;
28
+ export declare function herdrPanes(socketPath: string): Promise<HerdrPane[]>;
29
+ /** Whether this process runs under a shared agent daemon such as the Codex app-server, whose HERDR_PANE_ID is not the agent's. */
30
+ export declare function underSharedDaemon(pid?: number): Promise<boolean>;
31
+ export interface ResolvedPane {
32
+ herdrSession: string;
33
+ socket: string;
34
+ pane: HerdrPane;
35
+ via: 'option' | 'session-id' | 'environment';
36
+ }
37
+ /**
38
+ * Finds the caller's herdr pane, in the order of _Agent_Claim_Command_: `--pane`, then the pane whose
39
+ * recorded agent session is the caller's session id, then HERDR_PANE_ID unless under a shared daemon.
40
+ */
41
+ export declare function resolveAgentPane(env: NodeJS.ProcessEnv, options?: {
42
+ pane?: string;
43
+ herdrSession?: string;
44
+ }): Promise<ResolvedPane>;