norn-cli 2.9.8 → 3.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 (35) hide show
  1. package/CLAUDE.md +68 -0
  2. package/NOW.md +170 -21
  3. package/README.md +226 -2
  4. package/demos/agent-workbench/README.md +156 -0
  5. package/demos/agent-workbench/agents.nornagent +87 -0
  6. package/demos/agent-workbench/contracts/domain-answer.schema.json +28 -0
  7. package/demos/agent-workbench/contracts/domain-question.schema.json +34 -0
  8. package/demos/agent-workbench/contracts/router-verdict.schema.json +43 -0
  9. package/demos/agent-workbench/contracts/ticket.schema.json +29 -0
  10. package/demos/agent-workbench/contracts/verdict.schema.json +48 -0
  11. package/demos/agent-workbench/fake-openai-server.js +128 -0
  12. package/demos/agent-workbench/fixtures/aligned-ticket.json +10 -0
  13. package/demos/agent-workbench/fixtures/cross-domain-ticket.json +10 -0
  14. package/demos/agent-workbench/fixtures/invalid-output-ticket.json +8 -0
  15. package/demos/agent-workbench/norn.config.json +15 -0
  16. package/demos/agent-workbench/prompts/ticket-router.md +11 -0
  17. package/demos/agent-workbench/workbench.norn +32 -0
  18. package/demos/mcp-ticket-testing/README.md +114 -0
  19. package/demos/mcp-ticket-testing/agents.nornagent +77 -0
  20. package/demos/mcp-ticket-testing/contracts/test-run.schema.json +31 -0
  21. package/demos/mcp-ticket-testing/expectations/proj-142.md +12 -0
  22. package/demos/mcp-ticket-testing/fixtures/proj-142.json +13 -0
  23. package/demos/mcp-ticket-testing/prompts/backend-tester.md +12 -0
  24. package/demos/mcp-ticket-testing/prompts/frontend-tester.md +14 -0
  25. package/demos/mcp-ticket-testing/prompts/reporter.md +10 -0
  26. package/demos/mcp-ticket-testing/servers/browser-server.js +133 -0
  27. package/demos/mcp-ticket-testing/servers/house-server.js +125 -0
  28. package/demos/mcp-ticket-testing/tickets.norn +32 -0
  29. package/dist/cli.js +185429 -111460
  30. package/package.json +71 -4
  31. package/playground/ai.norn +15 -0
  32. package/playground/ai_orchastration.nornagent +29 -0
  33. package/playground/knowedge_base/nexus_system_prompt.md +1 -0
  34. package/schemas/norn.config.schema.json +223 -0
  35. package/CHANGELOG.md +0 -1506
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "norn-cli",
3
3
  "displayName": "Norn",
4
4
  "description": "Version-controlled API and database tests. Author in VS Code, then run the same files from the CLI and CI.",
5
- "version": "2.9.8",
5
+ "version": "3.1.0",
6
6
  "publisher": "Norn-PeterKrustanov",
7
7
  "author": {
8
8
  "name": "Peter Krastanov"
@@ -32,7 +32,8 @@
32
32
  "test automation"
33
33
  ],
34
34
  "engines": {
35
- "vscode": "^1.108.1"
35
+ "vscode": "^1.108.1",
36
+ "node": ">=20.0.0"
36
37
  },
37
38
  "categories": [
38
39
  "Testing",
@@ -45,6 +46,7 @@
45
46
  "onLanguage:nornapi",
46
47
  "onLanguage:nornenv",
47
48
  "onLanguage:nornk8s",
49
+ "onLanguage:nornagent",
48
50
  "workspaceContains:**/norn.config.json",
49
51
  "onChatParticipant:norn.chat",
50
52
  "onView:norn.sidebarHome",
@@ -56,6 +58,8 @@
56
58
  "onCommand:norn.openTerminal",
57
59
  "onCommand:norn.terminal.focusRawTerminal",
58
60
  "onCommand:norn.debugSequence",
61
+ "onCommand:norn.debug.runToNextContractFailure",
62
+ "onCommand:norn.showAgentGraph",
59
63
  "onDebugResolve:norn"
60
64
  ],
61
65
  "main": "./dist/extension.js",
@@ -76,6 +80,17 @@
76
80
  "title": "Debug Sequence",
77
81
  "category": "Norn"
78
82
  },
83
+ {
84
+ "command": "norn.debug.runToNextContractFailure",
85
+ "title": "Run to Next Contract Failure",
86
+ "category": "Norn Debug",
87
+ "icon": "$(debug-continue)"
88
+ },
89
+ {
90
+ "command": "norn.showAgentGraph",
91
+ "title": "Show Agent Graph",
92
+ "category": "Norn"
93
+ },
79
94
  {
80
95
  "command": "norn.clearCookies",
81
96
  "title": "Clear Cookies",
@@ -241,6 +256,13 @@
241
256
  "when": "explorerResourceIsFolder",
242
257
  "group": "norn@2"
243
258
  }
259
+ ],
260
+ "debug/toolBar": [
261
+ {
262
+ "command": "norn.debug.runToNextContractFailure",
263
+ "when": "debugType == norn && debugState == stopped",
264
+ "group": "navigation@25"
265
+ }
244
266
  ]
245
267
  },
246
268
  "languages": [
@@ -317,6 +339,21 @@
317
339
  "dark": "./images/nornk8s-icon.svg"
318
340
  },
319
341
  "configuration": "./language-configuration.json"
342
+ },
343
+ {
344
+ "id": "nornagent",
345
+ "aliases": [
346
+ "Norn Agent",
347
+ "nornagent"
348
+ ],
349
+ "extensions": [
350
+ ".nornagent"
351
+ ],
352
+ "icon": {
353
+ "light": "./images/nornagent-icon.svg",
354
+ "dark": "./images/nornagent-icon.svg"
355
+ },
356
+ "configuration": "./language-configuration.json"
320
357
  }
321
358
  ],
322
359
  "grammars": [
@@ -347,6 +384,23 @@
347
384
  "language": "nornk8s",
348
385
  "scopeName": "source.nornk8s",
349
386
  "path": "./syntaxes/nornk8s.tmLanguage.json"
387
+ },
388
+ {
389
+ "language": "nornagent",
390
+ "scopeName": "source.nornagent",
391
+ "path": "./syntaxes/nornagent.tmLanguage.json"
392
+ }
393
+ ],
394
+ "semanticTokenScopes": [
395
+ {
396
+ "language": "norn",
397
+ "scopes": {
398
+ "variable": [
399
+ "variable.other.constant.norn",
400
+ "variable.other.constant",
401
+ "variable"
402
+ ]
403
+ }
350
404
  }
351
405
  ],
352
406
  "jsonValidation": [
@@ -362,6 +416,9 @@
362
416
  "breakpoints": [
363
417
  {
364
418
  "language": "norn"
419
+ },
420
+ {
421
+ "language": "nornagent"
365
422
  }
366
423
  ],
367
424
  "debuggers": [
@@ -374,6 +431,9 @@
374
431
  "breakpoints": [
375
432
  {
376
433
  "language": "norn"
434
+ },
435
+ {
436
+ "language": "nornagent"
377
437
  }
378
438
  ],
379
439
  "configurationAttributes": {
@@ -391,6 +451,10 @@
391
451
  "type": "string",
392
452
  "description": "Name of the sequence to debug."
393
453
  },
454
+ "recording": {
455
+ "type": "string",
456
+ "description": "Optional workspace-relative or absolute agent-run recording to replay offline."
457
+ },
394
458
  "env": {
395
459
  "type": "string",
396
460
  "description": "Environment name for this debug session. If omitted, Norn uses the currently selected environment."
@@ -563,8 +627,8 @@
563
627
  "@types/pg": "^8.18.0",
564
628
  "@types/tough-cookie": "^4.0.5",
565
629
  "@types/vscode": "^1.108.1",
566
- "@vscode/test-cli": "^0.0.12",
567
- "@vscode/test-electron": "^2.5.2",
630
+ "@vscode/test-cli": "^0.0.15",
631
+ "@vscode/test-electron": "^3.1.0",
568
632
  "@xterm/addon-fit": "^0.11.0",
569
633
  "@xterm/xterm": "^6.0.0",
570
634
  "esbuild": "^0.27.2",
@@ -575,12 +639,15 @@
575
639
  "typescript-eslint": "^8.52.0"
576
640
  },
577
641
  "dependencies": {
642
+ "@anthropic-ai/sdk": "^0.116.0",
643
+ "@google/genai": "^2.16.0",
578
644
  "@modelcontextprotocol/sdk": "^1.29.0",
579
645
  "ajv": "^8.17.1",
580
646
  "axios": "^1.13.2",
581
647
  "chalk": "^5.4.1",
582
648
  "mssql": "^12.2.0",
583
649
  "norn-cli": "^1.10.6",
650
+ "openai": "^6.49.0",
584
651
  "pg": "^8.20.0",
585
652
  "tough-cookie": "^6.0.0"
586
653
  },
@@ -0,0 +1,15 @@
1
+ import "./ai_orchastration.nornagent"
2
+
3
+ sequence SimpleNexusRun
4
+
5
+ var nexusReply = run Nexus "Open any website for me need to see if the mcp connection is working"
6
+
7
+ print "Result" | nexusReply
8
+
9
+ end sequence
10
+
11
+ sequence Test
12
+ run mcp list Time
13
+ run TimeTeller "what is the time"
14
+
15
+ end sequence
@@ -0,0 +1,29 @@
1
+ model gpt4o
2
+ provider openai
3
+ name gpt-4o
4
+ apiKey {{OPENAI_API}}
5
+ end model
6
+
7
+ mcp Playwright
8
+ transport stdio
9
+ command npx --yes @playwright/mcp@0.0.79 --headless --isolated --browser chrome
10
+ end mcp
11
+
12
+ mcp Time
13
+ transport http
14
+ url http://localhost:8811/mcp
15
+ header Authorization: Bearer {{$env.TIME_MCP_TOKEN}}
16
+ end mcp
17
+
18
+ agent Nexus
19
+ model gpt4o
20
+ system file "./knowedge_base/nexus_system_prompt.md"
21
+ mcp Playwright
22
+ end agent
23
+
24
+ agent TimeTeller
25
+ model gpt4o
26
+ mcp Time
27
+ system "When asked for the time you check the MCP server you have access to and check what the time is now."
28
+ end agent
29
+
@@ -0,0 +1 @@
1
+ You are Nexus you open a webpage when asked using the playwright mcp. They will ussualy provide you with a URL to open in the webpage, if you are not just try to open www.google.com and see if it works if you managed to open it this is success report back and wrap up.
@@ -66,6 +66,38 @@
66
66
  }
67
67
  }
68
68
  }
69
+ },
70
+ {
71
+ "label": "Norn config with contract mode",
72
+ "description": "Create a Norn config that auto-validates endpoint responses against synced contracts/ schemas.",
73
+ "body": {
74
+ "version": 1,
75
+ "contracts": {
76
+ "mode": "auto"
77
+ }
78
+ }
79
+ },
80
+ {
81
+ "label": "Norn config with agent limits",
82
+ "description": "Create a Norn config with global agent safeguards, automatic run recording, and a smaller local-provider output ceiling.",
83
+ "body": {
84
+ "version": 1,
85
+ "agents": {
86
+ "max_tokens": 16000,
87
+ "max_depth": 5,
88
+ "max_invocations": 25,
89
+ "max_turns": 100,
90
+ "contract_retries": 2,
91
+ "recording": {
92
+ "enabled": true
93
+ },
94
+ "providers": {
95
+ "local": {
96
+ "max_tokens": 4096
97
+ }
98
+ }
99
+ }
100
+ }
69
101
  }
70
102
  ],
71
103
  "properties": {
@@ -154,6 +186,50 @@
154
186
  }
155
187
  }
156
188
  ]
189
+ },
190
+ "contracts": {
191
+ "allOf": [
192
+ {
193
+ "$ref": "#/definitions/contractsSection"
194
+ }
195
+ ],
196
+ "defaultSnippets": [
197
+ {
198
+ "label": "Contracts section definition",
199
+ "description": "Turn on contract mode for endpoint-syntax requests.",
200
+ "body": {
201
+ "mode": "${1:auto}"
202
+ }
203
+ }
204
+ ]
205
+ },
206
+ "agents": {
207
+ "allOf": [
208
+ {
209
+ "$ref": "#/definitions/agentsSection"
210
+ }
211
+ ],
212
+ "defaultSnippets": [
213
+ {
214
+ "label": "Agent settings section definition",
215
+ "description": "Insert global agent limits, recording settings, and an optional provider-specific override.",
216
+ "body": {
217
+ "max_tokens": 16000,
218
+ "max_depth": 5,
219
+ "max_invocations": 25,
220
+ "max_turns": 100,
221
+ "contract_retries": 2,
222
+ "recording": {
223
+ "enabled": true
224
+ },
225
+ "providers": {
226
+ "${1:local}": {
227
+ "max_tokens": 4096
228
+ }
229
+ }
230
+ }
231
+ }
232
+ ]
157
233
  }
158
234
  },
159
235
  "definitions": {
@@ -260,6 +336,153 @@
260
336
  }
261
337
  }
262
338
  },
339
+ "contractsSection": {
340
+ "type": "object",
341
+ "additionalProperties": false,
342
+ "description": "Contract-mode settings. Contract mode auto-validates each endpoint-syntax response against the synced contracts/ schema for that operation and status.",
343
+ "properties": {
344
+ "_comment": {
345
+ "$ref": "#/definitions/comment",
346
+ "description": "Optional human-readable guidance ignored by Norn at runtime."
347
+ },
348
+ "mode": {
349
+ "type": "string",
350
+ "enum": [
351
+ "auto",
352
+ "off"
353
+ ],
354
+ "default": "off",
355
+ "description": "'auto' validates every endpoint-syntax request against its committed contracts/ schema (no assert lines needed). 'off' (default) disables contract mode; the --contracts CLI flag overrides this per run.",
356
+ "enumDescriptions": [
357
+ "Validate every endpoint-syntax response against its synced contract schema.",
358
+ "Disable automatic contract validation (default)."
359
+ ]
360
+ }
361
+ }
362
+ },
363
+ "agentProviderLimits": {
364
+ "type": "object",
365
+ "additionalProperties": false,
366
+ "description": "Agent limits for one model provider. These override global agents settings and are overridden by directives on an individual agent.",
367
+ "properties": {
368
+ "_comment": {
369
+ "$ref": "#/definitions/comment",
370
+ "description": "Optional human-readable guidance ignored by Norn at runtime."
371
+ },
372
+ "max_tokens": {
373
+ "type": "integer",
374
+ "minimum": 1,
375
+ "description": "Provider-specific maximum output-token ceiling for each agent invocation."
376
+ },
377
+ "max_depth": {
378
+ "type": "integer",
379
+ "minimum": 1,
380
+ "description": "Provider-specific maximum sub-agent invocation depth."
381
+ },
382
+ "max_invocations": {
383
+ "type": "integer",
384
+ "minimum": 1,
385
+ "description": "Provider-specific maximum total invocations in one top-level agent run."
386
+ },
387
+ "max_turns": {
388
+ "type": "integer",
389
+ "minimum": 1,
390
+ "description": "Provider-specific maximum model turns in one hop's tool loop. Each turn is a paid model call."
391
+ },
392
+ "contract_retries": {
393
+ "type": "integer",
394
+ "minimum": 0,
395
+ "description": "Provider-specific failed-attempt cap for correctable accepts or returns handoff violations."
396
+ }
397
+ }
398
+ },
399
+ "agentRecording": {
400
+ "type": "object",
401
+ "additionalProperties": false,
402
+ "description": "Automatic agent run recording. Norn keeps a fixed rolling maximum of the latest 20 generated recordings; retention is not configurable.",
403
+ "properties": {
404
+ "_comment": {
405
+ "$ref": "#/definitions/comment",
406
+ "description": "Optional human-readable guidance ignored by Norn at runtime."
407
+ },
408
+ "enabled": {
409
+ "type": "boolean",
410
+ "default": true,
411
+ "description": "Write an offline replay recording for completed agent runs. Enabled by default."
412
+ }
413
+ }
414
+ },
415
+ "agentsSection": {
416
+ "type": "object",
417
+ "additionalProperties": false,
418
+ "description": "Global recording behavior and global/provider-specific limits for agent runs. Per-agent .nornagent directives override limit values.",
419
+ "properties": {
420
+ "_comment": {
421
+ "$ref": "#/definitions/comment",
422
+ "description": "Optional human-readable guidance ignored by Norn at runtime."
423
+ },
424
+ "max_tokens": {
425
+ "type": "integer",
426
+ "minimum": 1,
427
+ "description": "Maximum output-token ceiling for each agent invocation. This is a ceiling, not a spend; hosted providers default to 16000 and local defaults to 4096."
428
+ },
429
+ "max_depth": {
430
+ "type": "integer",
431
+ "minimum": 1,
432
+ "description": "Maximum sub-agent invocation depth for one top-level agent run. Higher values can permit more model calls."
433
+ },
434
+ "max_invocations": {
435
+ "type": "integer",
436
+ "minimum": 1,
437
+ "description": "Maximum total agent invocations, including the root, within one top-level agent run."
438
+ },
439
+ "max_turns": {
440
+ "type": "integer",
441
+ "minimum": 1,
442
+ "description": "Maximum model turns in one hop's tool loop before the hop stops as truncated. Each turn is a paid model call; defaults to 100."
443
+ },
444
+ "contract_retries": {
445
+ "type": "integer",
446
+ "minimum": 0,
447
+ "description": "Failed-attempt cap for correctable accepts or returns violations at a sub-agent handoff. Set to 0 to fail immediately."
448
+ },
449
+ "recording": {
450
+ "allOf": [
451
+ {
452
+ "$ref": "#/definitions/agentRecording"
453
+ }
454
+ ],
455
+ "defaultSnippets": [
456
+ {
457
+ "label": "Agent recording settings",
458
+ "description": "Enable or disable automatic offline replay recordings.",
459
+ "body": {
460
+ "enabled": true
461
+ }
462
+ }
463
+ ]
464
+ },
465
+ "providers": {
466
+ "type": "object",
467
+ "additionalProperties": false,
468
+ "description": "Limits for a specific model provider. Provider values override global agents settings.",
469
+ "properties": {
470
+ "openai": {
471
+ "$ref": "#/definitions/agentProviderLimits"
472
+ },
473
+ "anthropic": {
474
+ "$ref": "#/definitions/agentProviderLimits"
475
+ },
476
+ "google": {
477
+ "$ref": "#/definitions/agentProviderLimits"
478
+ },
479
+ "local": {
480
+ "$ref": "#/definitions/agentProviderLimits"
481
+ }
482
+ }
483
+ }
484
+ }
485
+ },
263
486
  "mcpSection": {
264
487
  "type": "object",
265
488
  "additionalProperties": false,