@elevasis/sdk 1.35.0 → 1.36.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.
@@ -2607,8 +2607,10 @@ ${actionsList}
2607
2607
 
2608
2608
  - Batch independent tool calls in one iteration (faster execution)
2609
2609
  - Dependent operations need separate iterations (tool B needs tool A's result)
2610
- - "complete" cannot mix with tool-call${includeNavigateKnowledge ? "/navigate-knowledge" : ""}${includeMessageAction ? `
2610
+ - "complete" cannot mix with navigate-knowledge${includeNavigateKnowledge ? "" : " (when available)"}
2611
+ - "complete" can mix with tool-call when the tool is a fire-and-forget side effect and you do not need its result before ending${includeMessageAction ? `
2611
2612
  - Always send at least one message before completing
2613
+ - Send at most one message per iteration. Multiple messages in a session turn are collapsed into one visible assistant message.
2612
2614
  - When you have your answer, send message + complete in the SAME iteration. Never send a message alone then complete in a later iteration.
2613
2615
  - Never repeat or rephrase the same answer across iterations. One clear answer, then complete.` : ""}
2614
2616
 
@@ -2619,6 +2621,7 @@ ${actionsList}
2619
2621
 
2620
2622
  **Don't use "complete" when:**
2621
2623
  - You just called a tool and need its results
2624
+ - You used navigate-knowledge and need the newly loaded knowledge in the next iteration
2622
2625
  - More iterations are needed
2623
2626
 
2624
2627
  ## Examples
@@ -2749,11 +2752,12 @@ function buildToolsPrompt(tools) {
2749
2752
  section += "To call a tool, return a tool-call action:\n";
2750
2753
  section += '{\n "type": "tool-call",\n "id": "unique-id",\n "name": "tool-name",\n "input": { /* tool input matching schema */ }\n}\n\n';
2751
2754
  section += "**IMPORTANT RULES:**\n";
2752
- section += '1. "complete" CANNOT mix with tool-call or navigate-knowledge actions in the same response\n';
2753
- section += '2. "complete" CAN mix with message \u2014 always pair your final message with complete in the same iteration\n';
2754
- section += "3. To use tools, return ONLY tool-call actions, then wait for results in the next iteration\n";
2755
- section += "4. After receiving tool results, you can either call more tools OR complete with final answer\n";
2756
- section += "5. navigate-knowledge actions load new capabilities - tools become available in the next iteration\n";
2755
+ section += '1. "complete" CANNOT mix with navigate-knowledge actions in the same response\n';
2756
+ section += '2. "complete" CAN mix with message - always pair your final message with complete in the same iteration\n';
2757
+ section += '3. "complete" CAN mix with fire-and-forget tool-call actions when you do not need their results\n';
2758
+ section += "4. To use tools and inspect their results, return ONLY tool-call actions, then wait for results in the next iteration\n";
2759
+ section += "5. After receiving tool results, you can either call more tools OR complete with final answer\n";
2760
+ section += "6. navigate-knowledge actions load new capabilities - tools become available in the next iteration\n";
2757
2761
  return section + "\n";
2758
2762
  }
2759
2763
 
@@ -3978,12 +3982,35 @@ function validateActionSequence(actions) {
3978
3982
  }
3979
3983
  }
3980
3984
  }
3985
+ function normalizeSessionMessages(actions, sessionCapable) {
3986
+ if (!sessionCapable) {
3987
+ return actions;
3988
+ }
3989
+ const messages = actions.filter((action) => action.type === "message");
3990
+ if (messages.length <= 1) {
3991
+ return actions;
3992
+ }
3993
+ const collapsedText = messages.map((message) => message.text).join("\n\n");
3994
+ const collapsedMessage = { type: "message", text: collapsedText };
3995
+ let emittedCollapsedMessage = false;
3996
+ return actions.flatMap((action) => {
3997
+ if (action.type !== "message") {
3998
+ return [action];
3999
+ }
4000
+ if (emittedCollapsedMessage) {
4001
+ return [];
4002
+ }
4003
+ emittedCollapsedMessage = true;
4004
+ return [collapsedMessage];
4005
+ });
4006
+ }
3981
4007
  async function processActions(iterationContext, response) {
3982
4008
  validateActionSequence(response.nextActions);
4009
+ const normalizedActions = normalizeSessionMessages(response.nextActions, !!iterationContext.config.sessionCapable);
3983
4010
  let shouldComplete = false;
3984
4011
  const toolCalls = [];
3985
4012
  const otherActions = [];
3986
- for (const action of response.nextActions) {
4013
+ for (const action of normalizedActions) {
3987
4014
  if (action.type === "tool-call") {
3988
4015
  toolCalls.push(action);
3989
4016
  } else {
@@ -4010,6 +4037,9 @@ async function processActions(iterationContext, response) {
4010
4037
  }
4011
4038
  }
4012
4039
  }
4040
+ if (!shouldComplete && iterationContext.config.sessionCapable && toolCalls.length === 0 && normalizedActions.some((a) => a.type === "message") && !normalizedActions.some((a) => a.type === "navigate-knowledge")) {
4041
+ shouldComplete = true;
4042
+ }
4013
4043
  return { shouldComplete };
4014
4044
  }
4015
4045
 
@@ -6790,6 +6820,23 @@ function safeZodToJsonSchema(schema) {
6790
6820
  }
6791
6821
  return void 0;
6792
6822
  }
6823
+ function serializeWorkerError(err) {
6824
+ const errorRecord = err instanceof Error ? err : void 0;
6825
+ const errorMessage = errorRecord?.message ?? String(err);
6826
+ const errorCode = err !== null && typeof err === "object" && "code" in err ? String(err.code) : "unknown";
6827
+ const errorName = errorRecord?.name ?? (err !== null && typeof err === "object" && err.constructor?.name ? err.constructor.name : "Error");
6828
+ const rawDetails = err !== null && typeof err === "object" && "details" in err ? err.details : void 0;
6829
+ const rawContext = err !== null && typeof err === "object" && "context" in err ? err.context : void 0;
6830
+ const details = rawDetails !== null && typeof rawDetails === "object" ? rawDetails : void 0;
6831
+ const context = rawContext !== null && typeof rawContext === "object" ? rawContext : void 0;
6832
+ return {
6833
+ error: `${errorName}: ${errorMessage}`,
6834
+ errorName,
6835
+ errorCode,
6836
+ ...details ? { errorDetails: details } : {},
6837
+ ...context ? { errorContext: context } : {}
6838
+ };
6839
+ }
6793
6840
  function serializeNext(next) {
6794
6841
  if (next === null) return null;
6795
6842
  if (next.type === "linear") return { type: "linear", target: next.target };
@@ -6827,10 +6874,10 @@ async function executeWorkflow(workflow, input, context) {
6827
6874
  }
6828
6875
  function buildWorkerExecutionContext(params) {
6829
6876
  const { executionId } = params;
6830
- const postLog = (level, message) => {
6877
+ const postLog = (level, message, logContext) => {
6831
6878
  parentPort.postMessage({
6832
6879
  type: "log",
6833
- entry: { level, message, timestamp: (/* @__PURE__ */ new Date()).toISOString(), executionId }
6880
+ entry: { level, message, timestamp: (/* @__PURE__ */ new Date()).toISOString(), executionId, context: logContext }
6834
6881
  });
6835
6882
  };
6836
6883
  return {
@@ -6845,21 +6892,21 @@ function buildWorkerExecutionContext(params) {
6845
6892
  signal: params.signal,
6846
6893
  store: /* @__PURE__ */ new Map(),
6847
6894
  logger: {
6848
- debug: (msg) => {
6895
+ debug: (msg, logContext) => {
6849
6896
  console.log(`[debug] ${msg}`);
6850
- postLog("info", msg);
6897
+ postLog("info", msg, logContext);
6851
6898
  },
6852
- info: (msg) => {
6899
+ info: (msg, logContext) => {
6853
6900
  console.log(`[info] ${msg}`);
6854
- postLog("info", msg);
6901
+ postLog("info", msg, logContext);
6855
6902
  },
6856
- warn: (msg) => {
6903
+ warn: (msg, logContext) => {
6857
6904
  console.warn(`[warn] ${msg}`);
6858
- postLog("warn", msg);
6905
+ postLog("warn", msg, logContext);
6859
6906
  },
6860
- error: (msg) => {
6907
+ error: (msg, logContext) => {
6861
6908
  console.error(`[error] ${msg}`);
6862
- postLog("error", msg);
6909
+ postLog("error", msg, logContext);
6863
6910
  }
6864
6911
  },
6865
6912
  onMessageEvent: async (event) => {
@@ -6971,11 +7018,12 @@ function startWorker(org) {
6971
7018
  parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
6972
7019
  } catch (err) {
6973
7020
  const durationMs = Date.now() - startTime;
6974
- console.error(`[SDK-WORKER] Workflow '${resourceId}' failed (${durationMs}ms): ${String(err)}`);
7021
+ const serializedError = serializeWorkerError(err);
7022
+ console.error(`[SDK-WORKER] Workflow '${resourceId}' failed (${durationMs}ms): ${serializedError.error}`);
6975
7023
  parentPort.postMessage({
6976
7024
  type: "result",
6977
7025
  status: "failed",
6978
- error: String(err),
7026
+ ...serializedError,
6979
7027
  logs: [],
6980
7028
  metrics: { durationMs }
6981
7029
  });
@@ -7003,20 +7051,28 @@ function startWorker(org) {
7003
7051
  signal: localAbortController.signal
7004
7052
  });
7005
7053
  const output = await agentInstance.execute(input, context);
7054
+ const memorySnapshot = agentInstance.getMemorySnapshot();
7055
+ if (!memorySnapshot) {
7056
+ throw new Error("Agent did not produce memory snapshot");
7057
+ }
7006
7058
  const durationMs = Date.now() - startTime;
7007
7059
  console.log(`[SDK-WORKER] Agent '${resourceId}' completed (${durationMs}ms)`);
7008
- parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
7060
+ parentPort.postMessage({
7061
+ type: "result",
7062
+ status: "completed",
7063
+ output,
7064
+ memorySnapshot,
7065
+ logs,
7066
+ metrics: { durationMs }
7067
+ });
7009
7068
  } catch (err) {
7010
7069
  const durationMs = Date.now() - startTime;
7011
- const errorRecord = err instanceof Error ? err : void 0;
7012
- const errorMessage = errorRecord?.message ?? String(err);
7013
- err !== null && typeof err === "object" && "code" in err ? String(err.code) : "unknown";
7014
- const errorName = errorRecord?.name ?? (err !== null && typeof err === "object" && err.constructor?.name ? err.constructor.name : "Error");
7015
- console.error(`[SDK-WORKER] Agent '${resourceId}' failed (${durationMs}ms): [${errorName}] ${errorMessage}`);
7070
+ const serializedError = serializeWorkerError(err);
7071
+ console.error(`[SDK-WORKER] Agent '${resourceId}' failed (${durationMs}ms): ${serializedError.error}`);
7016
7072
  parentPort.postMessage({
7017
7073
  type: "result",
7018
7074
  status: "failed",
7019
- error: `${errorName}: ${errorMessage}`,
7075
+ ...serializedError,
7020
7076
  logs,
7021
7077
  metrics: { durationMs }
7022
7078
  });
@@ -7030,6 +7086,8 @@ function startWorker(org) {
7030
7086
  type: "result",
7031
7087
  status: "failed",
7032
7088
  error: `Resource not found: ${resourceId}`,
7089
+ errorName: "ResourceNotFoundError",
7090
+ errorCode: "resource_not_found",
7033
7091
  logs: []
7034
7092
  });
7035
7093
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/sdk",
3
- "version": "1.35.0",
3
+ "version": "1.36.0",
4
4
  "description": "SDK for building Elevasis organization resources",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,9 +58,9 @@
58
58
  "tsup": "^8.0.0",
59
59
  "typescript": "5.9.2",
60
60
  "zod": "^4.1.0",
61
- "@repo/core": "0.48.0",
62
- "@repo/eslint-config": "0.0.0",
63
- "@repo/typescript-config": "0.0.0"
61
+ "@repo/core": "0.49.0",
62
+ "@repo/typescript-config": "0.0.0",
63
+ "@repo/eslint-config": "0.0.0"
64
64
  },
65
65
  "scripts": {
66
66
  "lint": "eslint src --max-warnings 0",
@@ -11,6 +11,7 @@
11
11
  "agent": "operator-facing deployed-agent introspection",
12
12
  "session": "operator-facing session introspection",
13
13
  "queue": "HITL approval queue — surfaced in the UI",
14
+ "grant": "operator-facing public agent access management",
14
15
  "schedule": "operator-facing scheduler control",
15
16
  "note": "CLI-only in tenant context; /notes is monorepo-internal, not propagated",
16
17
  "ui": "infra-only dev toggle (ui:use-local / ui:use-published)",
@@ -0,0 +1,30 @@
1
+ # Agent grants, execution visualizer, and Operations sidebar release train
2
+
3
+ This train publishes coordinated platform updates across `@elevasis/core`, `@elevasis/ui`,
4
+ and `@elevasis/sdk`, then syncs the external template baseline.
5
+
6
+ ## What changes for tenant projects
7
+
8
+ 1. `@elevasis/sdk` adds `grant:list`, `grant:create`, and `grant:disable` for
9
+ managing public/code-gated agent access grants through the platform API.
10
+ 2. `@elevasis/ui` adds shared agent public/private controls and improves the
11
+ agent execution visualizer with per-iteration tool activity.
12
+ 3. `@elevasis/core` adds the grant audit activity contract used by platform
13
+ activity feeds.
14
+ 4. The template `.claude/registries/skill-coverage.json` now explicitly waives
15
+ the `grant` CLI domain as operator-facing access-management tooling.
16
+
17
+ ## Operator action
18
+
19
+ - Run the prepared external sync manifest from the SDK ship artifact.
20
+ - Verify each derived project updates `.claude/registries/skill-coverage.json`.
21
+ - After package baselines are bumped, verify derived package manifests point at
22
+ the newly published `@elevasis/core`, `@elevasis/ui`, and `@elevasis/sdk`
23
+ versions selected by the release steps.
24
+
25
+ ## Manual-review exclusions
26
+
27
+ Operations sidebar root-route parity for `external/nirvana-marketing` and
28
+ `external/ZentaraHQ` is intentionally excluded from this ship train. Their
29
+ root routes are project-specific merge-managed surfaces and should be reviewed
30
+ manually before adopting the template Operations manifest mount.
@@ -122,16 +122,19 @@ The API URL is centralized in `ui/src/lib/constants/api.ts`. In the current temp
122
122
 
123
123
  ## Route Structure
124
124
 
125
- Current top-level app sections:
126
-
127
- - `/` -- host-local dashboard entrypoint with quick links derived from `organizationModel.navigation.quickAccessSurfaceIds`
128
- - `/lead-gen/*` -- lead generation pages (`lists`, `companies`, `contacts`)
125
+ Current top-level app sections:
126
+
127
+ - `/` -- host-local dashboard entrypoint with quick links derived from `organizationModel.navigation.quickAccessSurfaceIds`
128
+ - `/public/agents/$slug` -- public, unauthenticated agent chat route for grant-backed public agents
129
+ - `/lead-gen/*` -- lead generation pages (`lists`, `companies`, `contacts`)
129
130
  - `/crm/*` -- CRM overview, pipeline, and deals
130
131
  - `/projects/*` -- delivery feature pages (projects, milestones, tasks, notes)
131
132
  - `/operations/*` -- operations overview, resources, command queue, command view, sessions, task scheduler
132
133
  - `/monitoring/*` -- execution logs, execution health, activity log, cost analytics, notifications
133
134
  - `/settings/*` -- account, organization, credentials, API keys, deployments, webhooks, and appearance
134
- - `/login` and `/auth-redirect` -- auth entry/callback routes
135
+ - `/login` and `/auth-redirect` -- auth entry/callback routes
136
+
137
+ Public routes use the `/public/` prefix and must render outside the authenticated app chrome. Public agent pages should import `PublicAgentChatRoutePage` from `@elevasis/ui/features/public-agent-chat` and mount it at `/public/agents/$slug`. Keep `/chat/$slug` only as a compatibility alias when preserving existing links.
135
138
 
136
139
  Section guards currently follow this pattern:
137
140
 
@@ -627,6 +627,8 @@ Knowledge map inspection. The `om:*` (Organization Model) commands expose knowle
627
627
 
628
628
  For the full command reference, flag details, and graph architecture, see the [knowledge:\* CLI documentation](/technical/features/knowledge/cli-and-skill).
629
629
 
630
+ In tenant projects, SDK read commands load `core/config/organization-model.ts` through the SDK's layout-aware TypeScript loader. The temporary bundle and dependency resolution are anchored at the package root that owns SDK dependencies, so hoisted pnpm workspaces resolve `esbuild` and `@elevasis/core` correctly. Missing org-model files still return the default model; malformed files or files with no usable export emit diagnostics. `knowledge:generate` / `om:generate` is the exception because it reads MDX and codegen inputs directly.
631
+
630
632
  **Quick reference:**
631
633
 
632
634
  ```bash