@vimhead.dev/norn-cli 0.1.0-tip.35725822562.1 → 0.1.0-tip.36148588553.1
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/assets/README.md +29 -2
- package/assets/docs/cli.md +25 -0
- package/assets/package.json +1 -1
- package/assets/packages/cli/src/cli.ts +19 -0
- package/assets/packages/cli/src/generated-build-info.ts +2 -2
- package/assets/packages/cli/src/internal/errors.ts +7 -0
- package/assets/packages/cli/src/workflow-loader.ts +8 -2
- package/assets/packages/cli/src/workflows-intro.ts +43 -0
- package/assets/packages/core/src/host-introduction.mjs +36 -0
- package/dist/cli.js +15 -0
- package/dist/generated-build-info.d.ts +2 -2
- package/dist/generated-build-info.js +2 -2
- package/dist/internal/errors.d.ts +3 -0
- package/dist/internal/errors.js +7 -0
- package/dist/workflow-loader.js +8 -2
- package/dist/workflows-intro.d.ts +3 -0
- package/dist/workflows-intro.js +37 -0
- package/package.json +2 -2
package/assets/README.md
CHANGED
|
@@ -149,8 +149,9 @@ methods, custom providers, and Norn's configuration directory, see
|
|
|
149
149
|
|
|
150
150
|
### 3. Optionally connect your harness
|
|
151
151
|
|
|
152
|
-
The shipped Pi and
|
|
153
|
-
|
|
152
|
+
The shipped Pi, Cursor, and Claude Code adapters deliver Norn documentation context and
|
|
153
|
+
[available workflow introductions](docs/cli.md#workflow-introduction) to your
|
|
154
|
+
harness at session start. Installing Norn alone does not register an adapter. Codex
|
|
154
155
|
and other harnesses can [invoke the CLI directly](docs/cli.md#javascript-client-and-other-harnesses).
|
|
155
156
|
|
|
156
157
|
#### Pi
|
|
@@ -183,6 +184,32 @@ outside `PATH`, start Cursor with an executable path:
|
|
|
183
184
|
NORN_EXECUTABLE=/absolute/path/to/norn cursor .
|
|
184
185
|
```
|
|
185
186
|
|
|
187
|
+
#### Claude Code
|
|
188
|
+
|
|
189
|
+
With Node and `norn` available on `PATH`, run in your terminal:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
claude plugin marketplace add vimhead/norn
|
|
193
|
+
claude plugin install norn@norn-adapters
|
|
194
|
+
claude
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
To select a different runtime, launch Claude Code with
|
|
198
|
+
`NORN_EXECUTABLE=/absolute/path/to/norn claude`. The plugin uses that runtime's
|
|
199
|
+
documentation and the workflows in the session's working directory; it does not
|
|
200
|
+
install Norn or configure authentication for Norn agents.
|
|
201
|
+
|
|
202
|
+
Context is added on startup, `/clear`, and compaction, not again on resume or
|
|
203
|
+
fork. Named-agent sessions (`--agent`) and subagent hook calls are excluded.
|
|
204
|
+
Existing instructions and prompts are preserved. Introduction failures appear as
|
|
205
|
+
hook errors without falling back to another runtime.
|
|
206
|
+
|
|
207
|
+
To test a checkout without installing the marketplace:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
claude --plugin-dir /absolute/path/to/norn
|
|
211
|
+
```
|
|
212
|
+
|
|
186
213
|
Need an adapter for another harness? [Open an issue](https://github.com/vimhead/norn/issues/new)
|
|
187
214
|
with the harness name.
|
|
188
215
|
|
package/assets/docs/cli.md
CHANGED
|
@@ -96,6 +96,31 @@ each argument, without relying on another `norn` installation on PATH.
|
|
|
96
96
|
inputs without filesystem or process access. Generating the introduction does not
|
|
97
97
|
inject it into prompts or alter Norn agent sessions.
|
|
98
98
|
|
|
99
|
+
## Workflow introduction
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
norn workflows intro
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Returns `{ "intro": "..." }` with caller guidance and an XML advertisement of the
|
|
106
|
+
current project's entrypoints. Each `<workflow>` contains its fully qualified
|
|
107
|
+
`<id>` and caller-facing `<instructions>` inside `<available_norn_workflows>`;
|
|
108
|
+
field values are XML-escaped. Internal steps and argument schemas are omitted.
|
|
109
|
+
For example, the [minimal project](../examples/minimal-workflow/README.md)
|
|
110
|
+
advertises `greet`; its full contract remains available through `workflows inspect greet`.
|
|
111
|
+
|
|
112
|
+
The command discovers the nearest project from the invocation directory and
|
|
113
|
+
loads current registration modules. No project, or a valid project with no
|
|
114
|
+
entrypoints, returns `{ "intro": "" }` with no preamble or XML wrapper. Invalid
|
|
115
|
+
configuration or incomplete registration fails rather than returning an empty
|
|
116
|
+
or partial advertisement. Like [other discovery commands](projects.md#import-and-reload),
|
|
117
|
+
it evaluates module-level code but does not execute workflows or create run state.
|
|
118
|
+
|
|
119
|
+
Adapters can request `docs intro` and `workflows intro` from the same selected
|
|
120
|
+
executable and deliver the returned text in that order. Neither command injects
|
|
121
|
+
context itself. The advertisement is a snapshot, not a replacement for live
|
|
122
|
+
workflow listing and inspection after source changes.
|
|
123
|
+
|
|
99
124
|
## Discover live contracts
|
|
100
125
|
|
|
101
126
|
```bash
|
package/assets/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.1.0-tip.
|
|
1
|
+
{"version":"0.1.0-tip.36148588553.1"}
|
|
@@ -67,6 +67,8 @@ import {
|
|
|
67
67
|
NORN_PROJECT_FILE_NAME,
|
|
68
68
|
} from "./workflow-loader.ts";
|
|
69
69
|
|
|
70
|
+
import { loadNornWorkflowsIntro } from "./workflows-intro.ts";
|
|
71
|
+
|
|
70
72
|
const RUNS_ROOT = join(".norn", "runs");
|
|
71
73
|
const RUN_WAIT_INTERVAL_MS = 1000;
|
|
72
74
|
const CLI_DESCRIPTION =
|
|
@@ -215,6 +217,20 @@ const COMMANDS: readonly CliCommand[] = [
|
|
|
215
217
|
examples: ["norn workflows list", "norn workflows list --all"],
|
|
216
218
|
execute: listWorkflows,
|
|
217
219
|
},
|
|
220
|
+
{
|
|
221
|
+
id: "workflows.intro",
|
|
222
|
+
path: ["workflows", "intro"],
|
|
223
|
+
description:
|
|
224
|
+
"Produce caller guidance and an XML advertisement of the current project's entrypoint workflows. Loads project modules but does not execute workflows or deliver context to agents.",
|
|
225
|
+
usage: "norn workflows intro",
|
|
226
|
+
output:
|
|
227
|
+
"JSON object with text under intro. Empty when no project or entrypoints exist; project-loading failures are errors, not partial advertisements.",
|
|
228
|
+
examples: ["norn workflows intro"],
|
|
229
|
+
execute: async (args) => {
|
|
230
|
+
assertNoExtraArgs("workflows intro", args);
|
|
231
|
+
writeJson({ intro: await loadNornWorkflowsIntro(process.cwd()) });
|
|
232
|
+
},
|
|
233
|
+
},
|
|
218
234
|
{
|
|
219
235
|
id: "workflows.inspect",
|
|
220
236
|
path: ["workflows", "inspect"],
|
|
@@ -485,6 +501,7 @@ const HELP_COMMAND_ORDER = [
|
|
|
485
501
|
"docs.inspect",
|
|
486
502
|
"docs.intro",
|
|
487
503
|
"workflows.list",
|
|
504
|
+
"workflows.intro",
|
|
488
505
|
"workflows.inspect",
|
|
489
506
|
"runs.start",
|
|
490
507
|
"runs.resume",
|
|
@@ -513,6 +530,8 @@ const HUMAN_COMMAND_SUMMARIES: Readonly<Record<string, string>> = {
|
|
|
513
530
|
"docs.intro":
|
|
514
531
|
"Produce a compact authoring introduction with local documentation pointers.",
|
|
515
532
|
"workflows.list": "List Norn workflows.",
|
|
533
|
+
"workflows.intro":
|
|
534
|
+
"Advertise current entrypoints with caller instructions as XML.",
|
|
516
535
|
"workflows.inspect": "Inspect a workflow schema and source.",
|
|
517
536
|
"runs.start": "Start a workflow run.",
|
|
518
537
|
"runs.resume": "Resume an interrupted gate or a restored checkpoint.",
|
|
@@ -2,8 +2,8 @@ import type { NornBuildInfo } from "./build-info.ts";
|
|
|
2
2
|
|
|
3
3
|
export const NORN_GENERATED_BUILD_INFO = {
|
|
4
4
|
"kind": "npm-registry",
|
|
5
|
-
"version": "0.1.0-tip.
|
|
6
|
-
"commit": "
|
|
5
|
+
"version": "0.1.0-tip.36148588553.1",
|
|
6
|
+
"commit": "bef15bd5452b3202f93f33f0b33bdf07a48f7ffc",
|
|
7
7
|
"packageSpec": "@vimhead.dev/norn-cli@tip",
|
|
8
8
|
"upgrade": {
|
|
9
9
|
"supported": false,
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { NornWorkflowDiagnostic } from "@vimhead.dev/norn";
|
|
2
2
|
import { AssertError } from "typebox/value";
|
|
3
3
|
|
|
4
|
+
export class NornProjectNotFoundError extends Error {
|
|
5
|
+
constructor(message: string) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "NornProjectNotFoundError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
4
11
|
export class NornProjectLoadError extends Error {
|
|
5
12
|
readonly code = "NORN_PROJECT_INVALID";
|
|
6
13
|
readonly isComplete = false;
|
|
@@ -24,7 +24,11 @@ import * as typeboxCompileModule from "typebox/compile";
|
|
|
24
24
|
import * as typeboxSchemaModule from "typebox/schema";
|
|
25
25
|
import * as typeboxValueModule from "typebox/value";
|
|
26
26
|
import { AssertError, Value } from "typebox/value";
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
errorMessage,
|
|
29
|
+
NornProjectLoadError,
|
|
30
|
+
NornProjectNotFoundError,
|
|
31
|
+
} from "./internal/errors.ts";
|
|
28
32
|
import {
|
|
29
33
|
assertCompatibleConfigurationOwners,
|
|
30
34
|
assertWorkflowDefinition,
|
|
@@ -169,7 +173,9 @@ async function findNearestNornProject(cwd: string): Promise<string> {
|
|
|
169
173
|
}
|
|
170
174
|
const parent = dirname(current);
|
|
171
175
|
if (parent === current)
|
|
172
|
-
throw new
|
|
176
|
+
throw new NornProjectNotFoundError(
|
|
177
|
+
`Could not find ${NORN_PROJECT_FILE_NAME} from ${cwd}`,
|
|
178
|
+
);
|
|
173
179
|
current = parent;
|
|
174
180
|
}
|
|
175
181
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { NornRegisteredWorkflowInfo } from "@vimhead.dev/norn";
|
|
2
|
+
import { NornProjectNotFoundError } from "./internal/errors.ts";
|
|
3
|
+
import { loadNornProject } from "./workflow-loader.ts";
|
|
4
|
+
|
|
5
|
+
export async function loadNornWorkflowsIntro(cwd: string): Promise<string> {
|
|
6
|
+
try {
|
|
7
|
+
const project = await loadNornProject(cwd);
|
|
8
|
+
return renderNornWorkflowsIntro(project.registry.list());
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if (error instanceof NornProjectNotFoundError) return "";
|
|
11
|
+
throw error;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function renderNornWorkflowsIntro(
|
|
16
|
+
workflows: readonly NornRegisteredWorkflowInfo[],
|
|
17
|
+
): string {
|
|
18
|
+
const entrypoints = workflows.filter((workflow) => workflow.isEntrypoint);
|
|
19
|
+
if (entrypoints.length === 0) return "";
|
|
20
|
+
return [
|
|
21
|
+
"The following Norn workflows are available in the current project.",
|
|
22
|
+
"When a task matches, use `workflows inspect <id>` with the runtime specified above to load its current contract.",
|
|
23
|
+
"Use `workflows list` to refresh this snapshot after workflow changes.",
|
|
24
|
+
"",
|
|
25
|
+
"<available_norn_workflows>",
|
|
26
|
+
...entrypoints.flatMap((workflow) => [
|
|
27
|
+
" <workflow>",
|
|
28
|
+
` <id>${escapeXml(workflow.id)}</id>`,
|
|
29
|
+
` <instructions>${escapeXml(workflow.instructions ?? "")}</instructions>`,
|
|
30
|
+
" </workflow>",
|
|
31
|
+
]),
|
|
32
|
+
"</available_norn_workflows>",
|
|
33
|
+
].join("\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function escapeXml(value: string): string {
|
|
37
|
+
return value
|
|
38
|
+
.replaceAll("&", "&")
|
|
39
|
+
.replaceAll("<", "<")
|
|
40
|
+
.replaceAll(">", ">")
|
|
41
|
+
.replaceAll('"', """)
|
|
42
|
+
.replaceAll("'", "'");
|
|
43
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
|
|
5
|
+
const runExecutable = promisify(execFile);
|
|
6
|
+
const MAX_INTRO_BYTES = 16_384;
|
|
7
|
+
|
|
8
|
+
function readIntroResponse({ stdout, group }) {
|
|
9
|
+
const response = JSON.parse(stdout);
|
|
10
|
+
if (
|
|
11
|
+
!response ||
|
|
12
|
+
typeof response !== "object" ||
|
|
13
|
+
typeof response.intro !== "string" ||
|
|
14
|
+
(group === "docs" && response.intro.trim().length === 0) ||
|
|
15
|
+
Buffer.byteLength(response.intro, "utf8") > MAX_INTRO_BYTES
|
|
16
|
+
)
|
|
17
|
+
throw new Error("Invalid Norn introduction response");
|
|
18
|
+
return response.intro;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function loadIntroduction({ executable, cwd, group }) {
|
|
22
|
+
const { stdout } = await runExecutable(executable, [group, "intro"], {
|
|
23
|
+
cwd,
|
|
24
|
+
timeout: 10_000,
|
|
25
|
+
maxBuffer: MAX_INTRO_BYTES * 2,
|
|
26
|
+
});
|
|
27
|
+
return readIntroResponse({ stdout, group });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function loadHostIntroduction({ executable, cwd }) {
|
|
31
|
+
const [intro, workflowsIntro] = await Promise.all([
|
|
32
|
+
loadIntroduction({ executable, cwd, group: "docs" }),
|
|
33
|
+
loadIntroduction({ executable, cwd, group: "workflows" }),
|
|
34
|
+
]);
|
|
35
|
+
return `<norn-docs-intro>\n${intro}\n</norn-docs-intro>${workflowsIntro ? `\n\n${workflowsIntro}` : ""}`;
|
|
36
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
loadNornProject,
|
|
65
65
|
NORN_PROJECT_FILE_NAME
|
|
66
66
|
} from "./workflow-loader.js";
|
|
67
|
+
import { loadNornWorkflowsIntro } from "./workflows-intro.js";
|
|
67
68
|
var RUNS_ROOT = join(".norn", "runs");
|
|
68
69
|
var RUN_WAIT_INTERVAL_MS = 1e3;
|
|
69
70
|
var CLI_DESCRIPTION = "Norn is a harness-agnostic runtime for agent-driven and code-driven workflows, built primarily for agents. Build workflows with the Norn SDK; use this JSON-native CLI to discover workflows, start or resume runs, inspect evidence, and manage the installed runtime.";
|
|
@@ -193,6 +194,18 @@ var COMMANDS = [
|
|
|
193
194
|
examples: ["norn workflows list", "norn workflows list --all"],
|
|
194
195
|
execute: listWorkflows
|
|
195
196
|
},
|
|
197
|
+
{
|
|
198
|
+
id: "workflows.intro",
|
|
199
|
+
path: ["workflows", "intro"],
|
|
200
|
+
description: "Produce caller guidance and an XML advertisement of the current project's entrypoint workflows. Loads project modules but does not execute workflows or deliver context to agents.",
|
|
201
|
+
usage: "norn workflows intro",
|
|
202
|
+
output: "JSON object with text under intro. Empty when no project or entrypoints exist; project-loading failures are errors, not partial advertisements.",
|
|
203
|
+
examples: ["norn workflows intro"],
|
|
204
|
+
execute: async (args) => {
|
|
205
|
+
assertNoExtraArgs("workflows intro", args);
|
|
206
|
+
writeJson({ intro: await loadNornWorkflowsIntro(process.cwd()) });
|
|
207
|
+
}
|
|
208
|
+
},
|
|
196
209
|
{
|
|
197
210
|
id: "workflows.inspect",
|
|
198
211
|
path: ["workflows", "inspect"],
|
|
@@ -441,6 +454,7 @@ var HELP_COMMAND_ORDER = [
|
|
|
441
454
|
"docs.inspect",
|
|
442
455
|
"docs.intro",
|
|
443
456
|
"workflows.list",
|
|
457
|
+
"workflows.intro",
|
|
444
458
|
"workflows.inspect",
|
|
445
459
|
"runs.start",
|
|
446
460
|
"runs.resume",
|
|
@@ -467,6 +481,7 @@ var HUMAN_COMMAND_SUMMARIES = {
|
|
|
467
481
|
"docs.inspect": "Locate matching documentation and examples offline.",
|
|
468
482
|
"docs.intro": "Produce a compact authoring introduction with local documentation pointers.",
|
|
469
483
|
"workflows.list": "List Norn workflows.",
|
|
484
|
+
"workflows.intro": "Advertise current entrypoints with caller instructions as XML.",
|
|
470
485
|
"workflows.inspect": "Inspect a workflow schema and source.",
|
|
471
486
|
"runs.start": "Start a workflow run.",
|
|
472
487
|
"runs.resume": "Resume an interrupted gate or a restored checkpoint.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const NORN_GENERATED_BUILD_INFO: {
|
|
2
2
|
readonly kind: "npm-registry";
|
|
3
|
-
readonly version: "0.1.0-tip.
|
|
4
|
-
readonly commit: "
|
|
3
|
+
readonly version: "0.1.0-tip.36148588553.1";
|
|
4
|
+
readonly commit: "bef15bd5452b3202f93f33f0b33bdf07a48f7ffc";
|
|
5
5
|
readonly packageSpec: "@vimhead.dev/norn-cli@tip";
|
|
6
6
|
readonly upgrade: {
|
|
7
7
|
readonly supported: false;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/generated-build-info.ts
|
|
2
2
|
var NORN_GENERATED_BUILD_INFO = {
|
|
3
3
|
"kind": "npm-registry",
|
|
4
|
-
"version": "0.1.0-tip.
|
|
5
|
-
"commit": "
|
|
4
|
+
"version": "0.1.0-tip.36148588553.1",
|
|
5
|
+
"commit": "bef15bd5452b3202f93f33f0b33bdf07a48f7ffc",
|
|
6
6
|
"packageSpec": "@vimhead.dev/norn-cli@tip",
|
|
7
7
|
"upgrade": {
|
|
8
8
|
"supported": false,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { NornWorkflowDiagnostic } from "@vimhead.dev/norn";
|
|
2
2
|
import { AssertError } from "typebox/value";
|
|
3
|
+
export declare class NornProjectNotFoundError extends Error {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
3
6
|
export declare class NornProjectLoadError extends Error {
|
|
4
7
|
readonly code = "NORN_PROJECT_INVALID";
|
|
5
8
|
readonly isComplete = false;
|
package/dist/internal/errors.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// src/internal/errors.ts
|
|
2
2
|
import { AssertError } from "typebox/value";
|
|
3
|
+
var NornProjectNotFoundError = class extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "NornProjectNotFoundError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
3
9
|
var NornProjectLoadError = class extends Error {
|
|
4
10
|
code = "NORN_PROJECT_INVALID";
|
|
5
11
|
isComplete = false;
|
|
@@ -31,6 +37,7 @@ function errorMessage(error) {
|
|
|
31
37
|
}
|
|
32
38
|
export {
|
|
33
39
|
NornProjectLoadError,
|
|
40
|
+
NornProjectNotFoundError,
|
|
34
41
|
NornRunStoppedError,
|
|
35
42
|
errorMessage,
|
|
36
43
|
schemaErrorMessage
|
package/dist/workflow-loader.js
CHANGED
|
@@ -22,7 +22,11 @@ import * as typeboxCompileModule from "typebox/compile";
|
|
|
22
22
|
import * as typeboxSchemaModule from "typebox/schema";
|
|
23
23
|
import * as typeboxValueModule from "typebox/value";
|
|
24
24
|
import { AssertError, Value } from "typebox/value";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
errorMessage,
|
|
27
|
+
NornProjectLoadError,
|
|
28
|
+
NornProjectNotFoundError
|
|
29
|
+
} from "./internal/errors.js";
|
|
26
30
|
import {
|
|
27
31
|
assertCompatibleConfigurationOwners,
|
|
28
32
|
assertWorkflowDefinition,
|
|
@@ -126,7 +130,9 @@ async function findNearestNornProject(cwd) {
|
|
|
126
130
|
}
|
|
127
131
|
const parent = dirname(current);
|
|
128
132
|
if (parent === current)
|
|
129
|
-
throw new
|
|
133
|
+
throw new NornProjectNotFoundError(
|
|
134
|
+
`Could not find ${NORN_PROJECT_FILE_NAME} from ${cwd}`
|
|
135
|
+
);
|
|
130
136
|
current = parent;
|
|
131
137
|
}
|
|
132
138
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/workflows-intro.ts
|
|
2
|
+
import { NornProjectNotFoundError } from "./internal/errors.js";
|
|
3
|
+
import { loadNornProject } from "./workflow-loader.js";
|
|
4
|
+
async function loadNornWorkflowsIntro(cwd) {
|
|
5
|
+
try {
|
|
6
|
+
const project = await loadNornProject(cwd);
|
|
7
|
+
return renderNornWorkflowsIntro(project.registry.list());
|
|
8
|
+
} catch (error) {
|
|
9
|
+
if (error instanceof NornProjectNotFoundError) return "";
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function renderNornWorkflowsIntro(workflows) {
|
|
14
|
+
const entrypoints = workflows.filter((workflow) => workflow.isEntrypoint);
|
|
15
|
+
if (entrypoints.length === 0) return "";
|
|
16
|
+
return [
|
|
17
|
+
"The following Norn workflows are available in the current project.",
|
|
18
|
+
"When a task matches, use `workflows inspect <id>` with the runtime specified above to load its current contract.",
|
|
19
|
+
"Use `workflows list` to refresh this snapshot after workflow changes.",
|
|
20
|
+
"",
|
|
21
|
+
"<available_norn_workflows>",
|
|
22
|
+
...entrypoints.flatMap((workflow) => [
|
|
23
|
+
" <workflow>",
|
|
24
|
+
` <id>${escapeXml(workflow.id)}</id>`,
|
|
25
|
+
` <instructions>${escapeXml(workflow.instructions ?? "")}</instructions>`,
|
|
26
|
+
" </workflow>"
|
|
27
|
+
]),
|
|
28
|
+
"</available_norn_workflows>"
|
|
29
|
+
].join("\n");
|
|
30
|
+
}
|
|
31
|
+
function escapeXml(value) {
|
|
32
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
loadNornWorkflowsIntro,
|
|
36
|
+
renderNornWorkflowsIntro
|
|
37
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vimhead.dev/norn-cli",
|
|
3
|
-
"version": "0.1.0-tip.
|
|
3
|
+
"version": "0.1.0-tip.36148588553.1",
|
|
4
4
|
"description": "Harness-agnostic runtime for agent-driven and code-driven workflows, built primarily for agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
|
44
44
|
"jiti": "^2.7.0",
|
|
45
45
|
"typebox": "^1.3.34",
|
|
46
|
-
"@vimhead.dev/norn": "0.1.0-tip.
|
|
46
|
+
"@vimhead.dev/norn": "0.1.0-tip.36148588553.1"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "node ../../scripts/build-package.ts"
|