norn-cli 4.3.1 → 4.4.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 +7 -7
- package/dist/cli.js +48 -23
- package/dist/knowledgeIndexWorker.js +13 -5
- package/package.json +22 -15
- package/schemas/norn.config.schema.json +1 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ That means you can:
|
|
|
27
27
|
- `.nornenv` files for environments and secrets
|
|
28
28
|
- `.nornapi` files for reusable endpoint definitions
|
|
29
29
|
- `.nornsql` files for database queries and commands
|
|
30
|
-
- `.nornagent` files for contract-checked AI agents and model-directed delegation
|
|
30
|
+
- `.nornai` or `.nornagent` files for contract-checked AI agents and model-directed delegation
|
|
31
31
|
- syntax highlighting, IntelliSense, and diagnostics
|
|
32
32
|
- response inspection, JSON diffing, and click-to-generate assertions
|
|
33
33
|
- tagged and parameterized test execution in VS Code and the CLI
|
|
@@ -140,7 +140,7 @@ Norn can call MCP tools from sequences without leaving the `.norn` runtime. MCP
|
|
|
140
140
|
|
|
141
141
|
A server can be declared in two places, and an alias resolves through them in this order:
|
|
142
142
|
|
|
143
|
-
1. an `mcp <Alias> ... end mcp` block in a `.
|
|
143
|
+
1. an `mcp <Alias> ... end mcp` block in a `.nornai` sidecar the file imports — see
|
|
144
144
|
[Contract-Checked Agent Graphs](#contract-checked-agent-graphs), and prefer this when agents
|
|
145
145
|
use the server too, because the file then says what it connects to;
|
|
146
146
|
2. `mcp.servers` in the nearest `norn.config.json`.
|
|
@@ -194,7 +194,7 @@ Behavior:
|
|
|
194
194
|
|
|
195
195
|
## Contract-Checked Agent Graphs
|
|
196
196
|
|
|
197
|
-
Define agents in an imported `.nornagent` sidecar. An agent can grant another
|
|
197
|
+
Define agents in an imported `.nornai` or `.nornagent` sidecar. Both extensions use the same syntax and behavior. An agent can grant another
|
|
198
198
|
agent through `agents`; the callee then appears to the calling model as an
|
|
199
199
|
ordinary tool. Its `accepts` schema constrains and validates the generated tool
|
|
200
200
|
input, and its `returns` schema validates the result before it travels back up
|
|
@@ -277,7 +277,7 @@ Deterministic `run mcp` steps resolve the same aliases, so a server can be prove
|
|
|
277
277
|
with no model and no cost:
|
|
278
278
|
|
|
279
279
|
```norn
|
|
280
|
-
import "./agents.
|
|
280
|
+
import "./agents.nornai"
|
|
281
281
|
|
|
282
282
|
test sequence ServersUp
|
|
283
283
|
var tools = run mcp list House
|
|
@@ -290,7 +290,7 @@ shape end to end: a browser agent, a backend agent narrowed on the same custom s
|
|
|
290
290
|
reporter, and a `judge` over the expected test cases.
|
|
291
291
|
|
|
292
292
|
A prompt that outgrows its sidecar can live in its own file instead. `describe`
|
|
293
|
-
and `system` both accept `file <path>`, resolved relative to the
|
|
293
|
+
and `system` both accept `file <path>`, resolved relative to the agent sidecar
|
|
294
294
|
file just like an import:
|
|
295
295
|
|
|
296
296
|
```nornagent
|
|
@@ -309,7 +309,7 @@ Run the graph from an ordinary sequence; the same nested contract and retry
|
|
|
309
309
|
trace appears in VS Code and the CLI:
|
|
310
310
|
|
|
311
311
|
```norn
|
|
312
|
-
import "./agents.
|
|
312
|
+
import "./agents.nornai"
|
|
313
313
|
|
|
314
314
|
test sequence RouteTicket
|
|
315
315
|
var ticket = run readJson "./ticket.json"
|
|
@@ -370,7 +370,7 @@ fixture. `--from` accepts a unique agent name or canonical path such as
|
|
|
370
370
|
onward runs live against the current graph.
|
|
371
371
|
|
|
372
372
|
**Norn: Show Agent Graph**, or the CodeLens on any agent block, draws the graph
|
|
373
|
-
for
|
|
373
|
+
for an agent sidecar: who calls whom, the `accepts`/`returns` contract on each
|
|
374
374
|
boundary, and how each one turned out. Hover an agent or a boundary for the full
|
|
375
375
|
detail — models, timings, usage, prompts, payloads, contract issues.
|
|
376
376
|
|
package/dist/cli.js
CHANGED
|
@@ -157480,6 +157480,12 @@ var fs36 = __toESM(require("fs"));
|
|
|
157480
157480
|
var fsPromises = __toESM(require("fs/promises"));
|
|
157481
157481
|
var path42 = __toESM(require("path"));
|
|
157482
157482
|
|
|
157483
|
+
// src/agents/agentSidecarPath.ts
|
|
157484
|
+
function isAgentSidecarPath(filePath) {
|
|
157485
|
+
const lowerPath = filePath.toLowerCase();
|
|
157486
|
+
return lowerPath.endsWith(".nornagent") || lowerPath.endsWith(".nornai");
|
|
157487
|
+
}
|
|
157488
|
+
|
|
157483
157489
|
// src/parser.ts
|
|
157484
157490
|
var path4 = __toESM(require("path"));
|
|
157485
157491
|
|
|
@@ -158940,6 +158946,7 @@ function parseNornAgentFile(content, sourcePath) {
|
|
|
158940
158946
|
let pendingMcp;
|
|
158941
158947
|
let pendingKnowledge;
|
|
158942
158948
|
let sawAgent = false;
|
|
158949
|
+
let sawMcpDeclaration = false;
|
|
158943
158950
|
const reportBareMcpAlias = (mcp) => {
|
|
158944
158951
|
errors.push(parseError(
|
|
158945
158952
|
mcp.lineNumber,
|
|
@@ -159508,6 +159515,7 @@ end model`,
|
|
|
159508
159515
|
}
|
|
159509
159516
|
const mcpMatch = trimmed.match(new RegExp(`^mcp\\s+(${IDENTIFIER})$`, "i"));
|
|
159510
159517
|
if (mcpMatch) {
|
|
159518
|
+
sawMcpDeclaration = true;
|
|
159511
159519
|
const alias = mcpMatch[1];
|
|
159512
159520
|
let invalid = false;
|
|
159513
159521
|
if (sawAgent) {
|
|
@@ -159900,11 +159908,11 @@ end model`,
|
|
|
159900
159908
|
"agent-knowledge-end-missing"
|
|
159901
159909
|
));
|
|
159902
159910
|
}
|
|
159903
|
-
if (models.size === 0) {
|
|
159904
|
-
errors.push(parseError(0, "
|
|
159911
|
+
if (!sawMcpDeclaration && models.size === 0) {
|
|
159912
|
+
errors.push(parseError(0, "An agent sidecar must declare at least one model block.", "agent-model-required"));
|
|
159905
159913
|
}
|
|
159906
|
-
if (agentNames.size === 0) {
|
|
159907
|
-
errors.push(parseError(0, "
|
|
159914
|
+
if (!sawMcpDeclaration && agentNames.size === 0) {
|
|
159915
|
+
errors.push(parseError(0, "An agent sidecar must declare at least one agent.", "agent-required"));
|
|
159908
159916
|
}
|
|
159909
159917
|
const localScope = new Map(agents.map((agent) => [agent.name.toLowerCase(), agent]));
|
|
159910
159918
|
for (const validationError of validateAgentScope(localScope, { checkUnknownReferences: false })) {
|
|
@@ -160491,6 +160499,15 @@ async function resolveImports(text, baseDir, readFile4, alreadyImported = /* @__
|
|
|
160491
160499
|
}
|
|
160492
160500
|
for (const imp of imports) {
|
|
160493
160501
|
const absolutePath = path4.resolve(baseDir, imp.path);
|
|
160502
|
+
if (imp.path.toLowerCase().endsWith(".ai")) {
|
|
160503
|
+
errors.push({
|
|
160504
|
+
path: imp.path,
|
|
160505
|
+
error: "The .ai extension is not supported for Norn agent sidecars. Rename the file to .nornai and update the import.",
|
|
160506
|
+
lineNumber: imp.lineNumber,
|
|
160507
|
+
blocking: true
|
|
160508
|
+
});
|
|
160509
|
+
continue;
|
|
160510
|
+
}
|
|
160494
160511
|
if (imp.path.endsWith(".nornsql")) {
|
|
160495
160512
|
const importedSqlPaths = sqlImportedPathsBySource.get(sourceFilePath);
|
|
160496
160513
|
if (importedSqlPaths.has(absolutePath)) {
|
|
@@ -160534,7 +160551,7 @@ async function resolveImports(text, baseDir, readFile4, alreadyImported = /* @__
|
|
|
160534
160551
|
}
|
|
160535
160552
|
continue;
|
|
160536
160553
|
}
|
|
160537
|
-
if (imp.path
|
|
160554
|
+
if (isAgentSidecarPath(imp.path)) {
|
|
160538
160555
|
const importedAgentPaths = agentImportedPathsBySource.get(sourceFilePath);
|
|
160539
160556
|
if (importedAgentPaths.has(absolutePath)) {
|
|
160540
160557
|
continue;
|
|
@@ -160739,7 +160756,7 @@ end sequence`);
|
|
|
160739
160756
|
}
|
|
160740
160757
|
const directAgentScope = agentDefinitionsBySource.get(sourceFilePath);
|
|
160741
160758
|
const directAgentImportsByPath = new Map(
|
|
160742
|
-
imports.filter((imp) => imp.path
|
|
160759
|
+
imports.filter((imp) => isAgentSidecarPath(imp.path)).map((imp) => [path4.resolve(baseDir, imp.path), imp])
|
|
160743
160760
|
);
|
|
160744
160761
|
for (const validationError of validateAgentScope(directAgentScope, {
|
|
160745
160762
|
skipSameSourceChecks: true,
|
|
@@ -184867,7 +184884,7 @@ function resolveMcpServer(startPath, alias, envVariables) {
|
|
|
184867
184884
|
const server = config2.servers[alias];
|
|
184868
184885
|
if (!server) {
|
|
184869
184886
|
throw new Error(
|
|
184870
|
-
`Server alias '${alias}' was not declared by an 'mcp ${alias} ... end mcp' block in the
|
|
184887
|
+
`Server alias '${alias}' was not declared by an 'mcp ${alias} ... end mcp' block in the agent sidecar and was not found in ${NORN_CONFIG_FILENAME} mcp.servers`
|
|
184871
184888
|
);
|
|
184872
184889
|
}
|
|
184873
184890
|
return { filePath, server };
|
|
@@ -199538,7 +199555,15 @@ var AgentInvocationRunner = class {
|
|
|
199538
199555
|
throw new Error(`Agent root invocation index must be a positive integer, received '${rootInvocationIndex2}'.`);
|
|
199539
199556
|
}
|
|
199540
199557
|
const hopPath = `${agent.name}[${rootInvocationIndex2}]`;
|
|
199541
|
-
const hop = await this.invokeAgent(
|
|
199558
|
+
const hop = await this.invokeAgent(
|
|
199559
|
+
agent,
|
|
199560
|
+
input2,
|
|
199561
|
+
0,
|
|
199562
|
+
void 0,
|
|
199563
|
+
[],
|
|
199564
|
+
[...this.options.initialConversation ?? []],
|
|
199565
|
+
hopPath
|
|
199566
|
+
);
|
|
199542
199567
|
return { hop, definitions: [...this.definitions.values()] };
|
|
199543
199568
|
}
|
|
199544
199569
|
nextInvocationId() {
|
|
@@ -203394,7 +203419,7 @@ function walkSidecars(directory) {
|
|
|
203394
203419
|
if (entry.isDirectory()) {
|
|
203395
203420
|
return walkSidecars(candidate);
|
|
203396
203421
|
}
|
|
203397
|
-
return entry.isFile() && entry.name
|
|
203422
|
+
return entry.isFile() && isAgentSidecarPath(entry.name) ? [candidate] : [];
|
|
203398
203423
|
});
|
|
203399
203424
|
}
|
|
203400
203425
|
function discoverKnowledgeDeclarations(projectRoot) {
|
|
@@ -206653,7 +206678,7 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
|
|
|
206653
206678
|
};
|
|
206654
206679
|
}
|
|
206655
206680
|
if (!judgeDefinition) {
|
|
206656
|
-
const message = `Judge agent '${judgeName}' was not found in the
|
|
206681
|
+
const message = `Judge agent '${judgeName}' was not found in the agent sidecars imported directly by this .norn file.`;
|
|
206657
206682
|
errors.push(message);
|
|
206658
206683
|
await emitFailure(message, step);
|
|
206659
206684
|
return {
|
|
@@ -206693,7 +206718,7 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
|
|
|
206693
206718
|
const scope = getCurrentAgentScope();
|
|
206694
206719
|
const definition = scope?.get(parsedRun.agentName.toLowerCase());
|
|
206695
206720
|
if (!definition) {
|
|
206696
|
-
const message = `Agent '${parsedRun.agentName}' was not found in the
|
|
206721
|
+
const message = `Agent '${parsedRun.agentName}' was not found in the agent sidecars imported directly by this .norn file.`;
|
|
206697
206722
|
errors.push(message);
|
|
206698
206723
|
await emitFailure(message, step);
|
|
206699
206724
|
return {
|
|
@@ -206986,7 +207011,7 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
|
|
|
206986
207011
|
try {
|
|
206987
207012
|
const judgeAgent = getCurrentAgentScope()?.get(declaration.judgeAgentName.toLowerCase());
|
|
206988
207013
|
if (!judgeAgent) {
|
|
206989
|
-
throw new Error(`Judge agent '${declaration.judgeAgentName}' was not found in the
|
|
207014
|
+
throw new Error(`Judge agent '${declaration.judgeAgentName}' was not found in the agent sidecars imported directly by this .norn file.`);
|
|
206990
207015
|
}
|
|
206991
207016
|
const evaluatedSubject = evaluateSqlArgumentExpression(declaration.subjectExpression, runtimeVariables);
|
|
206992
207017
|
if (evaluatedSubject.error) {
|
|
@@ -207147,7 +207172,7 @@ ${describeUnmetExpectations(verdict).map((line2) => ` - ${line2}`).join("\n")}`
|
|
|
207147
207172
|
const scope = getCurrentAgentScope();
|
|
207148
207173
|
agent = scope?.get(parsed.agentName.toLowerCase());
|
|
207149
207174
|
if (!agent) {
|
|
207150
|
-
throw new Error(`Agent '${parsed.agentName}' was not found in the
|
|
207175
|
+
throw new Error(`Agent '${parsed.agentName}' was not found in the agent sidecars imported directly by this .norn file.`);
|
|
207151
207176
|
}
|
|
207152
207177
|
const evaluatedInput = evaluateSqlArgumentExpression(parsed.inputExpression, runtimeVariables);
|
|
207153
207178
|
if (evaluatedInput.error) {
|
|
@@ -212913,12 +212938,12 @@ function knowledgeCliHelp() {
|
|
|
212913
212938
|
return `
|
|
212914
212939
|
Norn knowledge membership and topic summary
|
|
212915
212940
|
|
|
212916
|
-
Usage: norn knowledge ls --explain [sidecar.nornagent]
|
|
212941
|
+
Usage: norn knowledge ls --explain [sidecar.nornai|sidecar.nornagent]
|
|
212917
212942
|
|
|
212918
212943
|
--explain List every source candidate as IN or OUT and name the deciding rule
|
|
212919
212944
|
-h, --help Show this help
|
|
212920
212945
|
|
|
212921
|
-
With no path, Norn discovers the one .nornagent sidecar declaring knowledge below the current
|
|
212946
|
+
With no path, Norn discovers the one .nornai or .nornagent sidecar declaring knowledge below the current
|
|
212922
212947
|
directory, and reports every declaration it holds.
|
|
212923
212948
|
`;
|
|
212924
212949
|
}
|
|
@@ -212938,7 +212963,7 @@ function parseKnowledgeCliArgs(args) {
|
|
|
212938
212963
|
} else if (argument.startsWith("-")) {
|
|
212939
212964
|
throw new Error(`Unknown knowledge option '${argument}'.`);
|
|
212940
212965
|
} else if (options.target) {
|
|
212941
|
-
throw new Error(`Unexpected knowledge argument '${argument}'. Provide at most one
|
|
212966
|
+
throw new Error(`Unexpected knowledge argument '${argument}'. Provide at most one agent sidecar path.`);
|
|
212942
212967
|
} else {
|
|
212943
212968
|
options.target = argument;
|
|
212944
212969
|
}
|
|
@@ -212955,14 +212980,14 @@ function discoverSidecars(directory) {
|
|
|
212955
212980
|
if (entry.isDirectory()) {
|
|
212956
212981
|
return SKIPPED_DIRECTORIES3.has(entry.name) ? [] : discoverSidecars(entryPath);
|
|
212957
212982
|
}
|
|
212958
|
-
return entry.isFile() && entry.name
|
|
212983
|
+
return entry.isFile() && isAgentSidecarPath(entry.name) ? [entryPath] : [];
|
|
212959
212984
|
});
|
|
212960
212985
|
}
|
|
212961
212986
|
function resolveSidecar(target) {
|
|
212962
212987
|
const resolved = path40.resolve(target ?? process.cwd());
|
|
212963
212988
|
if (fs34.existsSync(resolved) && fs34.statSync(resolved).isFile()) {
|
|
212964
|
-
if (!resolved
|
|
212965
|
-
throw new Error(`Knowledge target '${target}' is not a .nornagent sidecar.`);
|
|
212989
|
+
if (!isAgentSidecarPath(resolved)) {
|
|
212990
|
+
throw new Error(`Knowledge target '${target}' is not a .nornai or .nornagent sidecar.`);
|
|
212966
212991
|
}
|
|
212967
212992
|
return resolved;
|
|
212968
212993
|
}
|
|
@@ -212979,11 +213004,11 @@ function resolveSidecar(target) {
|
|
|
212979
213004
|
}
|
|
212980
213005
|
});
|
|
212981
213006
|
if (matches.length === 0) {
|
|
212982
|
-
throw new Error(`No
|
|
213007
|
+
throw new Error(`No agent sidecar knowledge declaration was found below '${resolved}'.`);
|
|
212983
213008
|
}
|
|
212984
213009
|
if (matches.length > 1) {
|
|
212985
213010
|
throw new Error(
|
|
212986
|
-
`More than one
|
|
213011
|
+
`More than one agent sidecar knowledge declaration was found. Provide one explicitly:
|
|
212987
213012
|
` + matches.map((match2) => ` ${path40.relative(resolved, match2)}`).join("\n")
|
|
212988
213013
|
);
|
|
212989
213014
|
}
|
|
@@ -213869,7 +213894,7 @@ Usage: norn <file.norn|directory> [options]
|
|
|
213869
213894
|
norn replay <recording.json> [--json] [--from <agent-or-hop>] [--env <name>]
|
|
213870
213895
|
norn secrets <command> [options]
|
|
213871
213896
|
norn contracts <sync|check> <file.nornapi> [options]
|
|
213872
|
-
norn knowledge ls --explain [sidecar.nornagent]
|
|
213897
|
+
norn knowledge ls --explain [sidecar.nornai|sidecar.nornagent]
|
|
213873
213898
|
|
|
213874
213899
|
When given a directory, recursively discovers .norn test sequences within
|
|
213875
213900
|
that directory and subdirectories.
|
|
@@ -214296,7 +214321,7 @@ async function main() {
|
|
|
214296
214321
|
}
|
|
214297
214322
|
const args = rawArgs[0] === "run" ? rawArgs.slice(1) : rawArgs;
|
|
214298
214323
|
if (args.length === 1 && (args[0] === "--version" || args[0] === "-V")) {
|
|
214299
|
-
console.log(`Norn CLI ${"4.
|
|
214324
|
+
console.log(`Norn CLI ${"4.4.0"}`);
|
|
214300
214325
|
return;
|
|
214301
214326
|
}
|
|
214302
214327
|
if (args.length === 0) {
|
|
@@ -7320,6 +7320,12 @@ function queryKnowledgeEditorFacts(query, options = {}) {
|
|
|
7320
7320
|
}
|
|
7321
7321
|
}
|
|
7322
7322
|
|
|
7323
|
+
// src/agents/agentSidecarPath.ts
|
|
7324
|
+
function isAgentSidecarPath(filePath) {
|
|
7325
|
+
const lowerPath = filePath.toLowerCase();
|
|
7326
|
+
return lowerPath.endsWith(".nornagent") || lowerPath.endsWith(".nornai");
|
|
7327
|
+
}
|
|
7328
|
+
|
|
7323
7329
|
// src/knowledge/knowledgeIndexBuilder.ts
|
|
7324
7330
|
var fs8 = __toESM(require("fs"));
|
|
7325
7331
|
var path10 = __toESM(require("path"));
|
|
@@ -7878,6 +7884,7 @@ function parseNornAgentFile(content, sourcePath) {
|
|
|
7878
7884
|
let pendingMcp;
|
|
7879
7885
|
let pendingKnowledge;
|
|
7880
7886
|
let sawAgent = false;
|
|
7887
|
+
let sawMcpDeclaration = false;
|
|
7881
7888
|
const reportBareMcpAlias = (mcp) => {
|
|
7882
7889
|
errors.push(parseError(
|
|
7883
7890
|
mcp.lineNumber,
|
|
@@ -8446,6 +8453,7 @@ end model`,
|
|
|
8446
8453
|
}
|
|
8447
8454
|
const mcpMatch = trimmed.match(new RegExp(`^mcp\\s+(${IDENTIFIER})$`, "i"));
|
|
8448
8455
|
if (mcpMatch) {
|
|
8456
|
+
sawMcpDeclaration = true;
|
|
8449
8457
|
const alias = mcpMatch[1];
|
|
8450
8458
|
let invalid = false;
|
|
8451
8459
|
if (sawAgent) {
|
|
@@ -8838,11 +8846,11 @@ end model`,
|
|
|
8838
8846
|
"agent-knowledge-end-missing"
|
|
8839
8847
|
));
|
|
8840
8848
|
}
|
|
8841
|
-
if (models.size === 0) {
|
|
8842
|
-
errors.push(parseError(0, "
|
|
8849
|
+
if (!sawMcpDeclaration && models.size === 0) {
|
|
8850
|
+
errors.push(parseError(0, "An agent sidecar must declare at least one model block.", "agent-model-required"));
|
|
8843
8851
|
}
|
|
8844
|
-
if (agentNames.size === 0) {
|
|
8845
|
-
errors.push(parseError(0, "
|
|
8852
|
+
if (!sawMcpDeclaration && agentNames.size === 0) {
|
|
8853
|
+
errors.push(parseError(0, "An agent sidecar must declare at least one agent.", "agent-required"));
|
|
8846
8854
|
}
|
|
8847
8855
|
const localScope = new Map(agents.map((agent) => [agent.name.toLowerCase(), agent]));
|
|
8848
8856
|
for (const validationError of validateAgentScope(localScope, { checkUnknownReferences: false })) {
|
|
@@ -10413,7 +10421,7 @@ function walkSidecars(directory) {
|
|
|
10413
10421
|
if (entry.isDirectory()) {
|
|
10414
10422
|
return walkSidecars(candidate);
|
|
10415
10423
|
}
|
|
10416
|
-
return entry.isFile() && entry.name
|
|
10424
|
+
return entry.isFile() && isAgentSidecarPath(entry.name) ? [candidate] : [];
|
|
10417
10425
|
});
|
|
10418
10426
|
}
|
|
10419
10427
|
function discoverKnowledgeDeclarations(projectRoot) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "norn-cli",
|
|
3
3
|
"displayName": "Norn",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "4.
|
|
4
|
+
"description": "Build version-controlled agentic flows in VS Code and run them from the CLI or CI.",
|
|
5
|
+
"version": "4.4.0",
|
|
6
6
|
"publisher": "Norn-PeterKrustanov",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Peter Krastanov"
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"onLanguage:nornk8s",
|
|
49
49
|
"onLanguage:nornagent",
|
|
50
50
|
"workspaceContains:**/*.nornagent",
|
|
51
|
+
"workspaceContains:**/*.nornai",
|
|
51
52
|
"workspaceContains:**/norn.config.json",
|
|
52
53
|
"onChatParticipant:norn.chat",
|
|
53
54
|
"onView:norn.sidebarHome",
|
|
@@ -55,12 +56,12 @@
|
|
|
55
56
|
"onCommand:norn.importPostmanEnvironment",
|
|
56
57
|
"onCommand:norn.createStarterCatalog",
|
|
57
58
|
"onCommand:norn.createSqlStarterFiles",
|
|
58
|
-
"onCommand:norn.createMcpStarterConfig",
|
|
59
59
|
"onCommand:norn.openTerminal",
|
|
60
60
|
"onCommand:norn.terminal.focusRawTerminal",
|
|
61
61
|
"onCommand:norn.debugSequence",
|
|
62
62
|
"onCommand:norn.debug.runToNextContractFailure",
|
|
63
63
|
"onCommand:norn.showAgentGraph",
|
|
64
|
+
"onCommand:norn.chatWithAgent",
|
|
64
65
|
"onCommand:norn.showAgentRunResults",
|
|
65
66
|
"onDebugResolve:norn"
|
|
66
67
|
],
|
|
@@ -93,6 +94,11 @@
|
|
|
93
94
|
"title": "Show Agent Graph",
|
|
94
95
|
"category": "Norn"
|
|
95
96
|
},
|
|
97
|
+
{
|
|
98
|
+
"command": "norn.chatWithAgent",
|
|
99
|
+
"title": "Chat With Agent",
|
|
100
|
+
"category": "Norn"
|
|
101
|
+
},
|
|
96
102
|
{
|
|
97
103
|
"command": "norn.showAgentRunResults",
|
|
98
104
|
"title": "Show Agent Run Results",
|
|
@@ -136,7 +142,11 @@
|
|
|
136
142
|
{
|
|
137
143
|
"command": "norn.openTerminal",
|
|
138
144
|
"title": "Open Terminal",
|
|
139
|
-
"category": "Norn"
|
|
145
|
+
"category": "Norn",
|
|
146
|
+
"icon": {
|
|
147
|
+
"light": "./images/nornapi-icon.svg",
|
|
148
|
+
"dark": "./images/nornapi-icon.svg"
|
|
149
|
+
}
|
|
140
150
|
},
|
|
141
151
|
{
|
|
142
152
|
"command": "norn.terminal.focusRawTerminal",
|
|
@@ -188,11 +198,6 @@
|
|
|
188
198
|
"title": "Open Norn Starter Catalogue",
|
|
189
199
|
"category": "Norn"
|
|
190
200
|
},
|
|
191
|
-
{
|
|
192
|
-
"command": "norn.createMcpStarterConfig",
|
|
193
|
-
"title": "Create MCP Starter Config",
|
|
194
|
-
"category": "Norn"
|
|
195
|
-
},
|
|
196
201
|
{
|
|
197
202
|
"command": "norn.encryptSecretAtLine",
|
|
198
203
|
"title": "Encrypt Secret At Line",
|
|
@@ -262,11 +267,6 @@
|
|
|
262
267
|
"command": "norn.createStarterCatalog",
|
|
263
268
|
"when": "explorerResourceIsFolder",
|
|
264
269
|
"group": "norn@1"
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
"command": "norn.createMcpStarterConfig",
|
|
268
|
-
"when": "explorerResourceIsFolder",
|
|
269
|
-
"group": "norn@2"
|
|
270
270
|
}
|
|
271
271
|
],
|
|
272
272
|
"debug/toolBar": [
|
|
@@ -275,6 +275,12 @@
|
|
|
275
275
|
"when": "debugType == norn && debugState == stopped",
|
|
276
276
|
"group": "navigation@25"
|
|
277
277
|
}
|
|
278
|
+
],
|
|
279
|
+
"editor/title": [
|
|
280
|
+
{
|
|
281
|
+
"command": "norn.openTerminal",
|
|
282
|
+
"group": "navigation"
|
|
283
|
+
}
|
|
278
284
|
]
|
|
279
285
|
},
|
|
280
286
|
"languages": [
|
|
@@ -359,7 +365,8 @@
|
|
|
359
365
|
"nornagent"
|
|
360
366
|
],
|
|
361
367
|
"extensions": [
|
|
362
|
-
".nornagent"
|
|
368
|
+
".nornagent",
|
|
369
|
+
".nornai"
|
|
363
370
|
],
|
|
364
371
|
"icon": {
|
|
365
372
|
"light": "./images/nornagent-icon.svg",
|
|
@@ -486,7 +486,7 @@
|
|
|
486
486
|
"agentsSection": {
|
|
487
487
|
"type": "object",
|
|
488
488
|
"additionalProperties": false,
|
|
489
|
-
"description": "Global recording behavior and global/provider-specific limits for agent runs. Per-agent .nornagent directives override limit values.",
|
|
489
|
+
"description": "Global recording behavior and global/provider-specific limits for agent runs. Per-agent .nornai or .nornagent directives override limit values.",
|
|
490
490
|
"properties": {
|
|
491
491
|
"_comment": {
|
|
492
492
|
"$ref": "#/definitions/comment",
|