@elevasis/sdk 1.55.0 → 1.56.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elevasis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @elevasis/sdk
2
+
3
+ SDK for building Elevasis organization resources — agents, workflows, and the CLI that deploys them.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pnpm add @elevasis/sdk
9
+ ```
10
+
11
+ ## Published surface
12
+
13
+ | Subpath | Contains |
14
+ | ---------------------------- | ------------------------------------------------------------------------- |
15
+ | `@elevasis/sdk` | Resource definitions, the registry, and its validators |
16
+ | `@elevasis/sdk/worker` | The worker-thread authoring surface: `Agent`, `Workflow`, collectors |
17
+ | `@elevasis/sdk/node` | Node-only helpers |
18
+ | `@elevasis/sdk/test-utils` | Test helpers for resource authors |
19
+
20
+ The package also installs an `elevasis-sdk` binary. Run `elevasis-sdk --help` for the command set;
21
+ every authenticated command accepts `--prod` to target production rather than a local API.
22
+
23
+ ## Relationship to `@elevasis/core`
24
+
25
+ The SDK inlines the `@repo/core` types it re-exports, so no `@elevasis/core` specifier survives in
26
+ the shipped declarations. That makes the SDK a second sanctioned route onto capabilities core does
27
+ not publish directly — import them from here rather than reaching for a core subpath that does not
28
+ resolve.
29
+
30
+ ## License
31
+
32
+ MIT — see [LICENSE](./LICENSE).
package/dist/cli.cjs CHANGED
@@ -49577,7 +49577,7 @@ var init_package = __esm({
49577
49577
  "package.json"() {
49578
49578
  package_default = {
49579
49579
  name: "@elevasis/sdk",
49580
- version: "1.55.0",
49580
+ version: "1.56.0",
49581
49581
  description: "SDK for building Elevasis organization resources",
49582
49582
  type: "module",
49583
49583
  bin: {
@@ -44,15 +44,8 @@ interface KnowledgeNodeInput {
44
44
  summary: string;
45
45
  body: string;
46
46
  }
47
- interface KnowledgeSearchEntry {
48
- id: string;
49
- title: string;
50
- summary: string;
51
- bodyText: string;
52
- }
53
47
  interface CodegenResult {
54
48
  bodiesTsx: string;
55
- searchIndex: KnowledgeSearchEntry[];
56
49
  }
57
50
  /**
58
51
  * Compiles knowledge nodes into generated file contents.
@@ -71,4 +64,4 @@ interface ResolvedKnowledgeLayout {
71
64
  declare function runKnowledgeCodegen(layout: ResolvedKnowledgeLayout): Promise<void>;
72
65
 
73
66
  export { generateKnowledgeBodies, generateKnowledgeNodes, generateKnowledgeNodesTs, readKnowledgeNodeMdx, runKnowledgeCodegen };
74
- export type { CodegenResult, GenerateKnowledgeNodesOptions, GenerateKnowledgeNodesResult, KnowledgeCodegenNode, KnowledgeKind, KnowledgeNodeInput, KnowledgeSearchEntry, ResolvedKnowledgeLayout };
67
+ export type { CodegenResult, GenerateKnowledgeNodesOptions, GenerateKnowledgeNodesResult, KnowledgeCodegenNode, KnowledgeKind, KnowledgeNodeInput, ResolvedKnowledgeLayout };
@@ -393,9 +393,6 @@ To add a component:
393
393
  );
394
394
  }
395
395
  }
396
- function stripToPlainText(body) {
397
- return body.replace(/^(import|export)\s+.+$/gm, "").replace(/<[A-Z][^>]*>/g, "").replace(/<\/[A-Z][^>]*>/g, "").replace(/^#{1,6}\s+/gm, "").replace(/[*_`~]/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\n{3,}/g, "\n\n").trim();
398
- }
399
396
  var BODIES_HEADER = [
400
397
  "// @generated by generate-knowledge-bodies -- DO NOT EDIT",
401
398
  "// Regenerate: pnpm scaffold:sync",
@@ -457,11 +454,10 @@ async function generateKnowledgeBodies(nodes) {
457
454
  "> = {}",
458
455
  ""
459
456
  ].join("\n");
460
- return { bodiesTsx: bodiesTsx2, searchIndex: [] };
457
+ return { bodiesTsx: bodiesTsx2 };
461
458
  }
462
459
  const nodeComments = [];
463
460
  const mapEntries = [];
464
- const searchIndex = [];
465
461
  for (const node of nodes) {
466
462
  if (/^(import|export)\s+/m.test(node.body)) {
467
463
  throw new Error(
@@ -475,15 +471,13 @@ async function generateKnowledgeBodies(nodes) {
475
471
  });
476
472
  const fnBodyCode = String(compiled);
477
473
  validateComponents(node.id, fnBodyCode);
478
- const bodyText = stripToPlainText(node.body);
479
- searchIndex.push({ id: node.id, title: node.title, summary: node.summary, bodyText });
480
474
  nodeComments.push(`// Node: ${node.id} (${node.kind})`);
481
475
  mapEntries.push(` '${node.id}': makeKnowledgeComponent(${JSON.stringify(fnBodyCode)})`);
482
476
  }
483
477
  const mapBlock = `export const KNOWLEDGE_BODIES: Record<string, ComponentType<KnowledgeBodyProps>> = {
484
478
  ` + mapEntries.join(",\n") + "\n}\n";
485
479
  const bodiesTsx = BODIES_HEADER + FACTORY_BLOCK + MAP_HEADER + (nodeComments.length > 0 ? nodeComments.join("\n") + "\n\n" : "") + mapBlock;
486
- return { bodiesTsx, searchIndex };
480
+ return { bodiesTsx };
487
481
  }
488
482
  async function runKnowledgeCodegen(layout) {
489
483
  let nodes;
@@ -504,14 +498,9 @@ async function runKnowledgeCodegen(layout) {
504
498
  });
505
499
  nodes = result.nodes;
506
500
  }
507
- const { bodiesTsx, searchIndex } = await generateKnowledgeBodies(nodes);
501
+ const { bodiesTsx } = await generateKnowledgeBodies(nodes);
508
502
  mkdirSync(layout.generatedDir, { recursive: true });
509
503
  writeFileSync(resolve(layout.generatedDir, "knowledge-bodies.tsx"), bodiesTsx, "utf8");
510
- writeFileSync(
511
- resolve(layout.generatedDir, "knowledge-search-index.json"),
512
- JSON.stringify(searchIndex, null, 2) + "\n",
513
- "utf8"
514
- );
515
504
  }
516
505
 
517
506
  export { generateKnowledgeBodies, generateKnowledgeNodes, generateKnowledgeNodesTs, readKnowledgeNodeMdx, runKnowledgeCodegen };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/sdk",
3
- "version": "1.55.0",
3
+ "version": "1.56.0",
4
4
  "description": "SDK for building Elevasis organization resources",
5
5
  "type": "module",
6
6
  "bin": {
@@ -63,7 +63,7 @@
63
63
  "typescript": "5.9.2",
64
64
  "vitest": "^3.2.4",
65
65
  "zod": "^4.1.0",
66
- "@repo/core": "0.71.0",
66
+ "@repo/core": "0.72.0",
67
67
  "@repo/eslint-config": "0.0.0",
68
68
  "@repo/typescript-config": "0.0.0"
69
69
  },
@@ -162,7 +162,7 @@ Package entries indexed: 63.
162
162
  | Theme | `packages/ui/src/theme/README.md` | Published theme entry for downstream applications. | (not specified) |
163
163
  | Graph | `packages/ui/src/graph/README.md` | Published graph helper and visualization entry. | (not specified) |
164
164
  | Theme Presets | `packages/ui/src/theme/presets/README.md` | Published THEME_PRESETS tuple, ThemePresetName union, and ThemePresetEnum Zod enum, defined locally and kept manually aligned with the canonical list in packages/core/src/auth/multi-tenancy/theme-presets.ts. | (not specified) |
165
- | Knowledge | `packages/ui/src/knowledge/README.md` | Published knowledge browser primitives: Browser, Tree, NodeList, NodeView, SearchBar, MDX provider, and the generated KNOWLEDGE_BODIES map. | (not specified) |
165
+ | Knowledge | `packages/ui/src/knowledge/README.md` | Published knowledge browser primitives: Browser, Tree, NodeList, NodeView, SearchBar, MDX provider, and the KnowledgeBodiesMap type. Machinery only -- each consumer supplies its own compiled corpus via the required knowledgeBodies prop. | (not specified) |
166
166
 
167
167
  ---
168
168
 
@@ -226,9 +226,9 @@ Agent rules indexed: 19.
226
226
  | Platform | `rules/platform.md` | Platform conventions -- SDK workflows, agents, deployment, resource registry | Authoring a workflow or agent definition, or registering a resource in the registry. |
227
227
  | Deployment | `rules/deployment.md` | Deployment workflow -- check-first, dev vs prod, version bumping, common errors | Before any deploy -- a plain `run deploy` targets production by default. |
228
228
  | Content | `rules/content.md` | Building the content System behind the shipped pipeline, item, and distribution routes -- which recipe to read, and the catalog vocabulary that is model-owned rather than coded | Editing anything under `ui/src/routes/content/` -- items, pipelines, distributions, or a review gate. |
229
- | Execution Model | `rules/execution.md` | Execution model -- timeouts, memory, concurrency, org isolation, runtime constraints | Hitting a timeout, memory ceiling, concurrency limit, or org-isolation question at runtime. |
229
+ | Execution Model | `rules/execution.md` | Execution model -- per-step and agent timeouts, spend ceilings, memory, concurrency, org isolation | Hitting a timeout, memory ceiling, concurrency limit, or org-isolation question at runtime. |
230
230
  | Agent Runtime | `rules/agent-runtime.md` | Agent runtime behavior -- iteration response shape, session memory and replay, prose normalization, and why a redeploy is what makes a platform fix live | Debugging an agent turn -- a missing reply, a corrupted one, a session that forgot, or an unenforced schema. |
231
- | Error Handling | `rules/error-handling.md` | Error handling -- ExecutionError vs PlatformToolError, retry logic, no auto-retry | Writing or debugging a step handler that throws, catches, or retries. |
231
+ | Error Handling | `rules/error-handling.md` | Error handling -- ExecutionError vs PlatformToolError, retry logic, no auto-retry, /api/external error envelope | Writing or debugging a step handler that throws, catches, or retries. |
232
232
  | Observability | `rules/observability.md` | Observability -- context.logger API, execution inspection, step-level context | Adding logging to a step handler, or inspecting a past execution. |
233
233
 
234
234
  ### Orientation
@@ -875,7 +875,7 @@
875
875
  "subpath": "./knowledge",
876
876
  "kind": "subpath",
877
877
  "title": "Knowledge",
878
- "description": "Published knowledge browser primitives: Browser, Tree, NodeList, NodeView, SearchBar, MDX provider, and the generated KNOWLEDGE_BODIES map.",
878
+ "description": "Published knowledge browser primitives: Browser, Tree, NodeList, NodeView, SearchBar, MDX provider, and the KnowledgeBodiesMap type. Machinery only -- each consumer supplies its own compiled corpus via the required knowledgeBodies prop.",
879
879
  "group": "Visual",
880
880
  "order": 3,
881
881
  "sourcePath": "packages/ui/src/knowledge/index.ts",
@@ -948,7 +948,7 @@
948
948
  {
949
949
  "packageName": "@elevasis/sdk",
950
950
  "title": "Execution Model",
951
- "description": "Execution model -- timeouts, memory, concurrency, org isolation, runtime constraints",
951
+ "description": "Execution model -- per-step and agent timeouts, spend ceilings, memory, concurrency, org isolation",
952
952
  "group": "Operations",
953
953
  "order": 4,
954
954
  "loadWhen": "Hitting a timeout, memory ceiling, concurrency limit, or org-isolation question at runtime.",
@@ -968,7 +968,7 @@
968
968
  {
969
969
  "packageName": "@elevasis/sdk",
970
970
  "title": "Error Handling",
971
- "description": "Error handling -- ExecutionError vs PlatformToolError, retry logic, no auto-retry",
971
+ "description": "Error handling -- ExecutionError vs PlatformToolError, retry logic, no auto-retry, /api/external error envelope",
972
972
  "group": "Operations",
973
973
  "order": 6,
974
974
  "loadWhen": "Writing or debugging a step handler that throws, catches, or retries.",
@@ -1,33 +1,33 @@
1
- # @elevasis/ui/knowledge
2
-
3
- Read-only browser primitives for the Organization Model knowledge graph.
4
-
5
- ## Surface
6
-
7
- | Export | Purpose |
8
- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
9
- | `KnowledgeBrowser` | Selected-node detail pane. Tree/search now live in the feature sidebar. |
10
- | `KnowledgeTree` | By-feature primary tree with hierarchical features and multi-governance duplication. |
11
- | `KnowledgeNodeList` | Legacy flat list of node summary cards; exported for compatibility. |
12
- | `KnowledgeNodeView` | Single knowledge-node detail view using `NodeDescribeShell` and relationship groups. |
13
- | `KnowledgeSearchBar` | Client-side search over `_generated/knowledge-search-index.json`. |
1
+ # @elevasis/ui/knowledge
2
+
3
+ Read-only browser primitives for the Organization Model knowledge graph.
4
+
5
+ ## Surface
6
+
7
+ | Export | Purpose |
8
+ | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
9
+ | `KnowledgeBrowser` | Selected-node detail pane. Tree/search now live in the feature sidebar. |
10
+ | `KnowledgeTree` | By-feature primary tree with hierarchical features and multi-governance duplication. |
11
+ | `KnowledgeNodeList` | Legacy flat list of node summary cards; exported for compatibility. |
12
+ | `KnowledgeNodeView` | Single knowledge-node detail view using `NodeDescribeShell` and relationship groups. |
13
+ | `KnowledgeSearchBar` | Client-side search built in-memory from the live `knowledgeNodes` prop. |
14
14
  | `KnowledgeNodeDetailRouteView` | Shared `/knowledge/$nodeId` content route view; apps keep TanStack route adapters and navigation wiring local. |
15
- | `KnowledgeRouteIds` helpers | Decode route ids, resolve Knowledge route targets, and derive route labels for app-local breadcrumbs. |
16
- | `KnowledgeSidebarMiddle` | Deprecated legacy sidebar middle section; active sidebar lives under `features/knowledge/sidebar`. |
17
- | `KNOWLEDGE_ITEMS` | Deprecated default sidebar nav items retained for compatibility. |
18
- | `KnowledgeMDXProvider`, `useKnowledgeAllowlist`, `KNOWLEDGE_ALLOWLIST` | MDX runtime allowlist (`Card`, `Cards`, `Step`, `Steps`, `Callout`, `Tab`, `Tabs`). |
19
- | `KNOWLEDGE_BODIES` | Build-time-compiled MDX components keyed by node id. |
20
-
21
- ## Customization tiers
22
-
23
- 1. **Default** — mount `knowledgeManifest` from `@elevasis/ui/features/knowledge`.
24
- 2. **Extend** — pass `extraComponents` to `KnowledgeMDXProvider` or compose around the feature sidebar primitives.
25
- 3. **Replace** — call `@elevasis/core/knowledge` queries directly from project-owned routes.
26
-
27
- ## Codegen
28
-
29
- `KNOWLEDGE_BODIES` and the search index are regenerated by `pnpm scaffold:sync` (or `pnpm knowledge:generate` to run only the knowledge step). Source: `canonicalOrganizationModel.knowledge.nodes` from `@repo/elevasis-core`.
30
-
31
- The Vite plugin at `@elevasis/ui/vite-plugin-knowledge` re-runs codegen on `buildStart` and watches the OM source dir for HMR.
32
-
33
- Phase 1 is read-only. Phase 2 will move bodies into Supabase and ship via `mdx-bundler`.
15
+ | `KnowledgeRouteIds` helpers | Decode route ids, resolve Knowledge route targets, and derive route labels for app-local breadcrumbs. |
16
+ | `KnowledgeSidebarMiddle` | Deprecated legacy sidebar middle section; active sidebar lives under `features/knowledge/sidebar`. |
17
+ | `KNOWLEDGE_ITEMS` | Deprecated default sidebar nav items retained for compatibility. |
18
+ | `KnowledgeMDXProvider`, `useKnowledgeAllowlist`, `KNOWLEDGE_ALLOWLIST` | MDX runtime allowlist (`Card`, `Cards`, `Step`, `Steps`, `Callout`, `Tab`, `Tabs`). |
19
+ | `KnowledgeBodiesMap` | Type for the compiled MDX-component-by-node-id map. `@elevasis/ui` ships this type only, not a corpus. |
20
+
21
+ ## Customization tiers
22
+
23
+ 1. **Default** — mount `knowledgeManifest` from `@elevasis/ui/features/knowledge`.
24
+ 2. **Extend** — pass `extraComponents` to `KnowledgeMDXProvider` or compose around the feature sidebar primitives.
25
+ 3. **Replace** — call `@elevasis/core/knowledge` queries directly from project-owned routes.
26
+
27
+ ## Codegen
28
+
29
+ This package ships the machinery only, not a compiled corpus. Each consumer generates its own `knowledge-bodies.tsx` (matching `KnowledgeBodiesMap`) beside its own Organization Model and hands it to `ElevasisSystemsProvider` as the required `knowledgeBodies` prop. In the monorepo that lives at `packages/elevasis/core/config/knowledge/_generated/`, sourced from `canonicalOrganizationModel.knowledge.nodes`; in an external project it lives at `<project-root>/core/config/knowledge/_generated/`. Regenerate with `pnpm scaffold:sync` (or `pnpm knowledge:generate` for only the knowledge step).
30
+
31
+ The Vite plugin at `@elevasis/ui/vite-plugin-knowledge` re-runs codegen on `buildStart` and watches the OM source dir for HMR.
32
+
33
+ Phase 1 is read-only. Phase 2 will move bodies into Supabase and ship via `mdx-bundler`.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Error handling -- ExecutionError vs PlatformToolError, retry logic, no auto-retry
2
+ description: Error handling -- ExecutionError vs PlatformToolError, retry logic, no auto-retry, /api/external error envelope
3
3
  paths:
4
4
  - operations/**
5
5
  ---
@@ -41,6 +41,17 @@ try {
41
41
  }
42
42
  ```
43
43
 
44
+ ## What Your Handler May Throw
45
+
46
+ `ExecutionError` is the class to throw from workflow and agent code. It carries a `context` record
47
+ and an `isRetryable()` the engine reads, which is why it is preferable to a bare `Error` -- a plain
48
+ throw arrives at the platform with no classification and no structured context.
49
+
50
+ Handler code runs in a worker thread, not in an API request. A throw there becomes an **execution
51
+ failure** recorded against the execution -- it never becomes an HTTP response body, so there is no
52
+ status code to pick and no envelope to shape. The envelope below is what you _receive_ when you call
53
+ the platform's own API, not what your handler produces.
54
+
44
55
  ## No Auto-Retry
45
56
 
46
57
  The platform does NOT automatically retry failed steps. Your handler is responsible for retry logic. Check `PlatformToolError.retryable` to decide whether retrying is safe.
@@ -60,6 +71,44 @@ The platform does NOT automatically retry failed steps. Your handler is responsi
60
71
  | `credentials_invalid` | No | Credential not found or expired |
61
72
  | `validation_error` | No | Invalid parameters passed to tool |
62
73
 
74
+ ## Error Bodies From `/api/external/*`
75
+
76
+ Every `/api/external/*` route returns the same error envelope. Tenants are the only consumers of
77
+ these routes, so this is the shape your API-key client parses:
78
+
79
+ ```json
80
+ {
81
+ "error": "human-readable message",
82
+ "code": "VALIDATION_ERROR",
83
+ "requestId": "correlates with server logs",
84
+ "fields": { "newResourceId": ["must differ from oldResourceId"] }
85
+ }
86
+ ```
87
+
88
+ `error` and `code` are always present. `requestId` is present on every error response -- quote it
89
+ when reporting a problem. `fields` appears only when the request body itself failed schema
90
+ validation. `retryAfter` (seconds) accompanies `RATE_LIMIT_EXCEEDED`, and `details` carries a
91
+ structured payload on some conflicts.
92
+
93
+ **`POST /api/external/resources/rename` changed shape -- read `code`, not just `error`.** It used to
94
+ build `{ error, code }` by hand, and then briefly returned `code: "VALIDATION_ERROR"` with a 400 for
95
+ _every_ failure, including ones that were not your fault. It now states the real cause:
96
+
97
+ | Failure | Status | `code` |
98
+ | --------------------------------------------- | ------ | ---------------------------------- |
99
+ | Body fails schema validation | 400 | `VALIDATION_ERROR` (with `fields`) |
100
+ | `newResourceId` already has execution history | 409 | `CONFLICT` |
101
+ | A database query or update failed | 500 | `INTERNAL_SERVER_ERROR` |
102
+
103
+ A client that branched on "400 means my input was wrong" now needs to distinguish 409 (rename to a
104
+ different id) from 500 (retry or report). A client reading only `error` as its diagnostic silently
105
+ loses that distinction -- the message text is not a stable contract, and `code` is.
106
+
107
+ **On any 5xx, `error` is generic by design.** The platform suppresses server-fault messages, so a 500
108
+ reads `"Internal server error"` rather than what actually broke -- that sentence was written for
109
+ whoever fixes the server, and it stays in the server's logs. `requestId` is what joins your failure
110
+ to that log line, so quote it when you report a 5xx rather than the message.
111
+
63
112
  ## CLI Transport Failures
64
113
 
65
114
  These are errors in the CLI you type commands into, not in your handler code. They are worth knowing because the natural reaction to one of them is the wrong reaction.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Execution model -- timeouts, memory, concurrency, org isolation, runtime constraints
2
+ description: Execution model -- per-step and agent timeouts, spend ceilings, memory, concurrency, org isolation
3
3
  paths:
4
4
  - operations/**
5
5
  ---
@@ -15,15 +15,71 @@ Each execution runs in an isolated Node.js worker thread spawned from the deploy
15
15
 
16
16
  ## Constraints
17
17
 
18
- | Constraint | Workflows | Agents |
19
- | ---------- | ------------------------------- | ----------------------------------------------------- |
20
- | Timeout | 300s (5 min) | 600s (10 min, configurable via `constraints.timeout`) |
21
- | Memory | 256MB hard limit | 256MB hard limit |
22
- | Disk | None (no persistent filesystem) | None |
18
+ | Constraint | Workflows | Agents |
19
+ | ---------- | ------------------------------- | ---------------------------------------------- |
20
+ | Timeout | 2h execution ceiling | 2h ceiling, lower it via `constraints.timeout` |
21
+ | Memory | 256MB hard limit | 256MB hard limit |
22
+ | Disk | None (no persistent filesystem) | None |
23
23
 
24
24
  - Platform enforces timeouts -- no handler code needed, worker terminates automatically.
25
25
  - Memory overflow crashes the worker. Other tenants are unaffected.
26
- - For long-running tasks, break work into multiple steps or use agents with extended timeout.
26
+ - The ceiling is a safety net against a runaway loop, not a duration budget. Bound the work you
27
+ actually want bounded with a per-step `timeout` (below) or `constraints.timeout`, rather than
28
+ relying on the ceiling to stop it.
29
+
30
+ ## Per-Step Timeouts
31
+
32
+ A workflow step may declare its own millisecond ceiling:
33
+
34
+ | Field | Applies to | Omitted |
35
+ | ---------------------- | ------------- | ----------------------------------------------------- |
36
+ | `WorkflowStep.timeout` | one step | the step is bounded only by the 2h execution ceiling |
37
+ | `constraints.timeout` | a whole agent | the agent is bounded only by the 2h execution ceiling |
38
+
39
+ `WorkflowConfig` has no `constraints` field on purpose. A per-workflow override would only restate
40
+ the execution ceiling; "this HTTP call should never take more than 5 seconds" is a property of the
41
+ step and has nowhere else to live.
42
+
43
+ **The two timeout failures are not the same failure, and the difference is whether a retry can
44
+ work.** A step that breaches its own `timeout` while the workflow still has budget left fails
45
+ **retryably** -- a slow third-party call is exactly what a retry exists for. A workflow that reaches
46
+ the 2h execution ceiling fails **non-retryably**: there is no budget left to retry inside. Neither
47
+ error class is exported from `@elevasis/sdk`, so branch on your own step's outcome rather than on
48
+ `instanceof`; the retryability distinction is what determines whether re-running is worth anything.
49
+
50
+ Declare a `timeout` on any step that calls something you do not control. Without one, a hung
51
+ integration call holds the whole workflow open for two hours.
52
+
53
+ ## Agent Spend Guards
54
+
55
+ `maxIterations` and `timeout` bound how MANY model calls an agent makes and how LONG it runs.
56
+ Neither bounds how much those calls cost. An agent on a large context or an expensive model can
57
+ spend without limit inside a budget it is technically respecting. Three `AgentConstraints` fields
58
+ close that:
59
+
60
+ | Constraint | Bounds | Default |
61
+ | ------------------------ | ------------------------------------------------ | ------------------- |
62
+ | `maxCostUsd` | total USD across every AI call in the turn | unset -- no ceiling |
63
+ | `maxTotalTokens` | total input + output tokens across every AI call | unset -- no ceiling |
64
+ | `maxIdenticalIterations` | consecutive byte-identical plans before stopping | 3 |
65
+
66
+ Set at least one of the first two on any agent you are not watching. Unset is genuinely unbounded,
67
+ not "bounded by something sensible".
68
+
69
+ **Reaching a spend ceiling fails the execution.** The stop reason is `spend_exhausted`, and the
70
+ worker reports `status: 'failed'` with `AgentSpendExhaustedError` -- deliberately, because an agent
71
+ that stopped at its ceiling did not finish its work, and reporting that as success is what makes the
72
+ failure mode invisible. Whatever the agent synthesized still travels on the failed result, so a
73
+ partial answer is not lost.
74
+
75
+ `spend_exhausted` is kept distinct from `budget_exhausted` (the `maxIterations` stop) because the
76
+ right response differs: an agent out of iterations may just need a larger `maxIterations`, while one
77
+ out of spend is the ceiling doing its job. Read the stop reason before raising either limit.
78
+
79
+ Ceilings are enforced only where the platform injects a usage collector, which is every
80
+ coordinator-run execution. Note that a **synchronous nested execution shares its parent's
81
+ collector**, so a parent's ceiling covers the agent and everything it invokes synchronously -- and
82
+ can therefore be reached by a child's spend.
27
83
 
28
84
  ## Concurrency
29
85
 
@@ -103,7 +103,9 @@ System field reference:
103
103
  - `actions` -- references to the cross-cutting actions domain.
104
104
  - `ontology` -- System-owned object, link, action, catalog, event, surface, interface, value-type, property, or group records.
105
105
  - `config` -- JSON-serializable settings local to this System.
106
- - `systems` -- nested child Systems. Use this for new recursive authoring; `subsystems` is a compatibility alias only.
106
+ - `systems` -- nested child Systems. Use this for new recursive authoring; `subsystems` is a retired spelling, accepted on input only.
107
+
108
+ **A parsed model no longer carries children under both keys.** Parsing used to mirror `systems` into `subsystems`, so either spelling could be read off any parsed System. That mirror is gone: children now live under whichever key the author wrote. Anything walking the tree must read `system.systems ?? system.subsystems` -- reading `subsystems` alone looked correct only because the mirror was filling it in.
107
109
 
108
110
  ## Ontology
109
111
 
@@ -941,6 +941,13 @@ export interface ElevasisSystemsProviderProps {
941
941
  /** Registered topbar action modules. OM node presence controls visibility; module supplies behavior. */
942
942
  topbarActions?: TopbarActionModule[]
943
943
  organizationModel?: ElevasisOrganizationModel
944
+ /**
945
+ * Compiled knowledge-node body components for this consumer's own corpus.
946
+ * Required, not defaulted: a missing corpus must fail to compile at the
947
+ * provider mount rather than render a blank panel at runtime. See
948
+ * `knowledge-corpus-injection.mdx`.
949
+ */
950
+ knowledgeBodies: KnowledgeBodiesMap
944
951
  timeRange?: TimeRange
945
952
  operationsApiUrl?: string
946
953
  operationsSSEManager?: SSEConnectionManagerLike
@@ -964,6 +971,8 @@ export interface ElevasisSystemsContextValue {
964
971
  resolvedSystems: ResolvedSystemModule[]
965
972
  organizationGraph: OrganizationGraphContextValue
966
973
  organizationModel?: OrganizationModel
974
+ /** Compiled knowledge-node body components for this consumer's own corpus. See `ElevasisSystemsProviderProps.knowledgeBodies`. */
975
+ knowledgeBodies: KnowledgeBodiesMap
967
976
  timeRange?: TimeRange
968
977
  operationsApiUrl?: string
969
978
  operationsSSEManager?: SSEConnectionManagerLike
@@ -92,8 +92,6 @@ operations/
92
92
  │ ├── metadata.ts # Trigger/integration/human-checkpoint metadata (starts empty)
93
93
  │ ├── resource-registry.test.ts
94
94
  │ ├── README.md
95
- │ ├── __tests__/
96
- │ │ └── sdk-test-utils.compat.ts # Shared test helpers -- assertResourceRegistry, runWorkflow
97
95
  │ ├── example/
98
96
  │ │ ├── echo.ts # Starter workflow
99
97
  │ │ ├── echo.test.ts
@@ -122,7 +120,7 @@ Convention seed for deployment mechanics that are not resource identity: trigger
122
120
 
123
121
  ### `operations/src/example/echo.ts`
124
122
 
125
- The starter workflow: one workflow per file with its own `config`, Zod `contract`, `steps` map, and `entryPoint`. Replace this domain with your own when ready. `operations/src/example/example-agent.ts` is the equivalent starter for an agent resource -- a minimal single-shot (non-session) `AgentDefinition` with no tools and no memory. Each has a matching `*.test.ts` file exercising it through the shared test helpers in `operations/src/__tests__/sdk-test-utils.compat.ts`.
123
+ The starter workflow: one workflow per file with its own `config`, Zod `contract`, `steps` map, and `entryPoint`. Replace this domain with your own when ready. `operations/src/example/example-agent.ts` is the equivalent starter for an agent resource -- a minimal single-shot (non-session) `AgentDefinition` with no tools and no memory. Each has a matching `*.test.ts` file exercising it through the published test helpers -- `runLinearWorkflow` (imported as `runWorkflow`) and `assertResourceRegistry`, both from `@elevasis/sdk/test-utils`.
126
124
 
127
125
  ### `operations/src/email-notification/index.ts`
128
126
 
@@ -33,7 +33,7 @@ description: "Auto-generated catalog of all published @elevasis/ui subpath expor
33
33
  | `@elevasis/ui/features/knowledge` | Features Knowledge | Features | Published knowledge feature manifest for downstream shells. |
34
34
  | `@elevasis/ui/features/notes` | Features Notes | Features | Published Notes panel view and supporting note components for shared right-panel integrations. |
35
35
  | `@elevasis/ui/features/right-panel-host` | Features Right Panel Host | Features | Published right-panel host provider, layer, trigger, keyboard shortcut, store, and view contract. |
36
- | `@elevasis/ui/knowledge` | Knowledge | Visual | Published knowledge browser primitives: Browser, Tree, NodeList, NodeView, SearchBar, MDX provider, and the generated KNOWLEDGE_BODIES map. |
36
+ | `@elevasis/ui/knowledge` | Knowledge | Visual | Published knowledge browser primitives: Browser, Tree, NodeList, NodeView, SearchBar, MDX provider, and the KnowledgeBodiesMap type. Machinery only -- each consumer supplies its own compiled corpus via the required knowledgeBodies prop. |
37
37
  | `@elevasis/ui/vite` | Vite | Build | Composite Vite plugin factory (elevasisVite) that bundles all @elevasis/ui Vite plugins into a single array for consumer vite.config.ts files. |
38
38
  | `@elevasis/ui/vite-plugin-knowledge` | Vite Plugin Knowledge | Build | Vite plugin that regenerates the build-time knowledge MDX bodies and search index, with HMR support. |
39
39
  | `@elevasis/ui/features/settings` | Features Settings | Features | Published settings feature surface for downstream shells. |