@orkestrel/tool 0.0.3 → 0.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orkestrel/tool",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Concrete LLM-callable tools for the @orkestrel line — workflow authoring, workspace editing, and sub-agent delegation, over the agent tool runtime, with pluggable stores. Part of the @orkestrel line.",
5
5
  "keywords": [
6
6
  "agent",
@@ -18,14 +18,13 @@
18
18
  "url": "git+https://github.com/orkestrel/tool.git"
19
19
  },
20
20
  "files": [
21
- "dist",
21
+ "dist/src",
22
22
  "README.md"
23
23
  ],
24
24
  "type": "module",
25
25
  "sideEffects": false,
26
26
  "main": "./dist/src/core/index.cjs",
27
27
  "module": "./dist/src/core/index.js",
28
- "types": "./dist/src/core/index.d.ts",
29
28
  "exports": {
30
29
  ".": {
31
30
  "import": {
@@ -53,21 +52,22 @@
53
52
  "access": "public"
54
53
  },
55
54
  "scripts": {
56
- "clean": "node -e \"try{require('node:fs').rmSync('dist',{recursive:true,force:true})}catch{}\"",
55
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
57
56
  "copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
58
- "tmp:txt": "node -e \"const fs=require('node:fs'),p=require('node:path');function walk(d){for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=p.join(d,e.name);if(e.isDirectory()){walk(f)}else if(!e.name.endsWith('.md')&&!e.name.endsWith('.txt')){const t=f+'.txt';if(!fs.existsSync(t)){fs.renameSync(f,t)}else{console.warn('Skipping '+f+' — target exists: '+t)}}}}try{walk('tmp')}catch(e){if(e.code!=='ENOENT')throw e}\"",
59
- "lint": "oxlint --config .oxlintrc.json --fix .",
57
+ "scaffold": "scaffold",
58
+ "lint": "oxlint --config .oxlintrc.json --fix --deny-warnings .",
60
59
  "check": "tsc --noEmit --project tsconfig.json && npm run check:src",
61
60
  "check:src": "npm run check:src:core && npm run check:src:server",
62
61
  "check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
63
62
  "check:src:server": "tsc --noEmit -p configs/src/tsconfig.server.json",
64
63
  "format": "oxfmt --config .oxfmtrc.json --write .",
65
64
  "format:check": "oxfmt --config .oxfmtrc.json --check .",
66
- "lint:check": "oxlint --config .oxlintrc.json .",
67
- "test": "npm run test:src && npm run test:guides",
65
+ "lint:check": "oxlint --config .oxlintrc.json --deny-warnings .",
66
+ "test": "npm run test:src && npm run test:policy && npm run test:guides",
68
67
  "test:src": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core --project src:server",
69
68
  "test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
70
69
  "test:src:server": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server",
70
+ "test:policy": "vitest run --config vite.config.ts --no-cache --reporter=dot --project policy",
71
71
  "test:guides": "vitest run --config vite.config.ts --reporter=dot --project guides",
72
72
  "build": "npm run clean && npm run build:src",
73
73
  "build:src": "npm run build:src:core && npm run build:src:server",
@@ -76,26 +76,28 @@
76
76
  "prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run build && npm test"
77
77
  },
78
78
  "dependencies": {
79
- "@orkestrel/agent": "^0.0.7",
80
- "@orkestrel/contract": "^0.0.5",
81
- "@orkestrel/database": "^0.0.5",
82
- "@orkestrel/relation": "^0.0.3",
83
- "@orkestrel/server": "^0.0.6",
84
- "@orkestrel/terminal": "^0.0.4",
85
- "@orkestrel/workflow": "^0.0.6"
79
+ "@orkestrel/agent": "^0.0.9",
80
+ "@orkestrel/contract": "^0.0.8",
81
+ "@orkestrel/database": "^0.0.6",
82
+ "@orkestrel/relation": "^0.0.6",
83
+ "@orkestrel/server": "^0.0.7",
84
+ "@orkestrel/terminal": "^0.0.5",
85
+ "@orkestrel/workflow": "^0.0.7"
86
86
  },
87
87
  "devDependencies": {
88
- "@microsoft/api-extractor": "^7.58.11",
89
- "@orkestrel/guide": "^0.0.5",
90
- "@types/node": "^26.1.1",
91
- "oxfmt": "^0.59.0",
92
- "oxlint": "^1.74.0",
88
+ "@microsoft/api-extractor": "^7.58.12",
89
+ "@orkestrel/guide": "^0.0.7",
90
+ "@orkestrel/scaffold": "^0.0.7",
91
+ "@types/node": "^26.1.2",
92
+ "@vitest/browser-playwright": "^4.1.10",
93
+ "oxfmt": "^0.61.0",
94
+ "oxlint": "^1.76.0",
93
95
  "typescript": "^6.0.3",
94
96
  "vite": "^8.1.5",
95
97
  "vite-plugin-dts": "^5.0.3",
96
98
  "vitest": "^4.1.10"
97
99
  },
98
100
  "engines": {
99
- "node": ">=22"
101
+ "node": ">=22.12.0"
100
102
  }
101
103
  }
@@ -1,12 +0,0 @@
1
- /**
2
- * The default `:name`-templated path {@link import('./factories.js').createTerminalRoutes}
3
- * mounts its GET (SSE) + POST (answer) routes under.
4
- */
5
- export declare const TERMINAL_ROUTES_PATH = "/terminals/:name";
6
- /**
7
- * The default SSE keepalive interval (in milliseconds)
8
- * {@link import('./factories.js').createTerminalRoutes} arms per open connection — a `: `
9
- * comment ping a conforming SSE parser ignores, keeping intermediary proxies from timing out an
10
- * otherwise-idle stream.
11
- */
12
- export declare const TERMINAL_KEEPALIVE_MS = 15000;
@@ -1,44 +0,0 @@
1
- import { TerminalManagerInterface } from '@orkestrel/terminal';
2
- import { TerminalRoute, TerminalRoutesOptions } from './types.js';
3
- /**
4
- * Build the two `TerminalManagerInterface` (`@orkestrel/terminal`) routes — a GET SSE stream and
5
- * a POST answer endpoint, both mounted on the SAME `:name`-templated path — that bridge a manager's
6
- * endpoints onto the wire, byte-compatible with `PromptClient`.
7
- *
8
- * @remarks
9
- * - **GET (SSE).** Optionally token-gated (`401` on mismatch), `404` when `name` names no
10
- * endpoint. Opens a stream, replays every currently-{@link import('@orkestrel/terminal').PendingPrompt}
11
- * as a `pending` frame, then live-forwards the manager's own `pending` / `expire` events scoped
12
- * to `name`. A `keepalive`-interval `: ` comment ping is armed via the injected `timer` (default
13
- * the host `setTimeout`). On the request's `AbortSignal` firing (client disconnect OR server
14
- * stop) the keepalive is cancelled, both listeners unsubscribed, and the stream ended — no
15
- * `shutdown` frame is sent, so a reconnecting client is never told the endpoint is gone.
16
- * - **POST (answer).** Same token + `404` checks, then reads the body capped at `options.limit`
17
- * bytes (`413` over, `manager.answer` never called — see {@link TerminalRoutesOptions.limit}),
18
- * parses the JSON body (`400` on invalid JSON, `422` when it isn't an `{ id, value }`
19
- * {@link import('@orkestrel/terminal').isAnswerPayload} shape), and routes it through
20
- * `manager.answer` — `204` on success, `404` for `'terminal'`, `422` for `'unknown'` / `'rejected'`.
21
- *
22
- * @remarks
23
- * The `token` option (a string OR a validator function — {@link TerminalToken}) is validated at
24
- * GET connect, on EVERY POST, and RE-VALIDATED on every keepalive tick of a live SSE stream — a
25
- * stream whose presented token stops validating is torn down rather than left streaming forever.
26
- * Concurrent POST answerers race first-write-wins — a late POST for an already-settled prompt
27
- * returns `422`.
28
- *
29
- * @param manager - The `TerminalManagerInterface` (`@orkestrel/terminal`) whose endpoints are bridged
30
- * @param options - See {@link TerminalRoutesOptions}
31
- * @returns Exactly two {@link TerminalRoute} records — GET then POST — sharing one path
32
- *
33
- * @example
34
- * ```ts
35
- * import { createTerminalRoutes } from '@src/server'
36
- * import { createTerminalManager } from '@orkestrel/terminal'
37
- *
38
- * const manager = createTerminalManager()
39
- * manager.add('assistant')
40
- * const routes = createTerminalRoutes(manager, { token: 'secret' })
41
- * // mount `routes` against any router accepting `{ method, path, handler }`
42
- * ```
43
- */
44
- export declare function createTerminalRoutes(manager: TerminalManagerInterface, options?: TerminalRoutesOptions): readonly TerminalRoute[];
@@ -1,60 +0,0 @@
1
- import { TimerHandler } from '@orkestrel/terminal';
2
- /** The HTTP method literal a {@link TerminalRoute} declares — the exact 7-literal union `@orkestrel/router`'s `Method` accepts. */
3
- export type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
4
- /**
5
- * The minimal route-dispatch context a {@link TerminalRoute} handler reads — exactly the frozen,
6
- * URL-decoded `:name` path param slice a router hands a matched handler.
7
- */
8
- export interface TerminalRouteContext {
9
- readonly params: Readonly<Record<string, string>>;
10
- }
11
- /**
12
- * One structural route record {@link import('./factories.js').createTerminalRoutes} returns — a
13
- * plain `{ method, path, handler }` shape carrying NO dependency on `@orkestrel/router`'s own
14
- * `Route` type, so a consumer mounts it against any router that accepts a two-arg
15
- * `(request, context) => Response | Promise<Response>` handler keyed by `method` + `path`.
16
- */
17
- export interface TerminalRoute {
18
- readonly method: Method;
19
- readonly path: string;
20
- readonly handler: (request: Request, context: TerminalRouteContext) => Response | Promise<Response>;
21
- }
22
- /**
23
- * The `token` gate a {@link TerminalRoutesOptions} may configure — a plain string compared for
24
- * equality against the `x-orkestrel-token` header, OR a validator function the consumer fully
25
- * controls, enabling expiry/rotation (a JWT `exp` check, a revocation-list lookup, anything
26
- * time-varying) that a fixed string cannot express. `undefined` disables the auth check entirely.
27
- */
28
- export type TerminalToken = string | ((value: string | undefined) => boolean);
29
- /**
30
- * Options for {@link import('./factories.js').createTerminalRoutes}.
31
- *
32
- * @remarks
33
- * - `path` — the shared `:name`-templated path both the GET (SSE) and POST (answer) routes
34
- * mount under; defaults to {@link import('./constants.js').TERMINAL_ROUTES_PATH}.
35
- * - `token` — a {@link TerminalToken}: a string is compared for equality against the
36
- * `x-orkestrel-token` header; a function receives the header's value (`undefined` when absent)
37
- * and returns whether it validates, letting the consumer roll/expire tokens out-of-band.
38
- * Validated at GET connect, on EVERY POST, and RE-VALIDATED on every keepalive tick of a live
39
- * SSE stream — a stream whose presented token stops validating (rotated, expired, revoked) is
40
- * torn down (the abort/self-heal teardown path, no `shutdown` frame) rather than left open
41
- * forever; the client reconnects and re-authenticates. Omitted ⇒ no auth check. Because
42
- * re-validation only happens on the keepalive tick, the revocation window equals the keepalive
43
- * interval — a token rejected/expired between ticks keeps streaming until the next one. A
44
- * validator function that THROWS is treated as rejection (fail-closed) at every call site.
45
- * - `keepalive` — the SSE comment-ping interval in milliseconds; defaults to
46
- * {@link import('./constants.js').TERMINAL_KEEPALIVE_MS}.
47
- * - `timer` — the injected {@link TimerHandler} driving the keepalive interval (default the host
48
- * `setTimeout`/`clearTimeout`), so a test drives the keepalive deterministically.
49
- * - `limit` — the maximum POST answer body size in bytes, streamed and enforced BEFORE JSON
50
- * parsing (ignoring any `Content-Length` header, so a lying header can never bypass the cap);
51
- * a body exceeding it is rejected `413` and `manager.answer` is never called. Defaults to
52
- * `@orkestrel/server`'s own `DEFAULT_BODY_LIMIT` (1 MiB).
53
- */
54
- export interface TerminalRoutesOptions {
55
- readonly path?: string;
56
- readonly token?: TerminalToken;
57
- readonly keepalive?: number;
58
- readonly timer?: TimerHandler;
59
- readonly limit?: number;
60
- }