@superpanel-sdk/runtime 0.0.1-internal.2 → 0.2.1

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.
@@ -11,7 +11,6 @@ import { toCaseContextViewRegistry, toFunctionRegistry } from './registry.js';
11
11
  const FATAL_CODES = new Set([
12
12
  'unknown-table',
13
13
  'unknown-field',
14
- 'missing-session',
15
14
  'missing-compute-fn',
16
15
  'cyclic-dependency',
17
16
  'multi-derived-forbidden',
@@ -38,7 +38,7 @@ function isCompanySchema(value) {
38
38
  return entries.length > 0 && entries.every(looksLikeTable);
39
39
  }
40
40
  function isSequenceSlots(value) {
41
- return isPlainObject(value) && looksLikeTable(value.session);
41
+ return isPlainObject(value) && Object.values(value).every(looksLikeTable);
42
42
  }
43
43
  /**
44
44
  * Resolve the config object from a dynamically imported module.
@@ -75,6 +75,7 @@ async function handleExecute(loaded, message) {
75
75
  data: message.data,
76
76
  runToken: message.runToken,
77
77
  getRequestId: () => message.logRequestId,
78
+ getTags: () => message.logTags,
78
79
  });
79
80
  try {
80
81
  return await host.execute(message.name, message.args);
@@ -14,6 +14,8 @@ export type SourceComputeHostOptions = {
14
14
  runToken?: string;
15
15
  /** Forwarded on every `ctx.api` RPC as `x-request-id`. */
16
16
  getRequestId?: () => string | undefined;
17
+ /** Forwarded to script log RPC calls. */
18
+ getTags?: () => string[] | undefined;
17
19
  };
18
20
  export interface SourceComputeHost extends ComputeHost {
19
21
  }
@@ -66,6 +66,7 @@ function resolveApiHost(options) {
66
66
  baseUrl: options.data.config.backendUrl,
67
67
  getToken: () => options.runToken,
68
68
  getRequestId: options.getRequestId,
69
+ getTags: options.getTags,
69
70
  });
70
71
  }
71
72
  return createFakeApiHost();
@@ -1,4 +1,5 @@
1
1
  import { ROW_ID_FIELD } from './schema.js';
2
+ import { createPlatformSessionTable, PLATFORM_SESSION_FIELDS } from './platform-session-fields.js';
2
3
  import { isReservedTableName, isRowIdField } from './row.js';
3
4
  import { resolveFuncName } from '../functions/func-ref.js';
4
5
  import { buildDependencyGraph } from './deps.js';
@@ -91,14 +92,9 @@ function validateCompanyRefs(company, issues) {
91
92
  */
92
93
  export function compileSlotSchema(company, sequenceSlots, options = {}) {
93
94
  const issues = [];
94
- const tables = {};
95
- if (!sequenceSlots.session) {
96
- issues.push({
97
- code: 'missing-session',
98
- message: 'Sequence slots must define a session table',
99
- path: 'session',
100
- });
101
- }
95
+ const tables = {
96
+ session: createPlatformSessionTable(),
97
+ };
102
98
  for (const [tableName, companyTable] of Object.entries(company)) {
103
99
  if (tableName === 'session' || isReservedTableName(tableName)) {
104
100
  if (isReservedTableName(tableName)) {
@@ -123,6 +119,8 @@ export function compileSlotSchema(company, sequenceSlots, options = {}) {
123
119
  };
124
120
  }
125
121
  for (const [tableName, tableView] of Object.entries(sequenceSlots)) {
122
+ if (!tableView)
123
+ continue;
126
124
  if (isReservedTableName(tableName)) {
127
125
  issues.push({
128
126
  code: 'reserved-table-name',
@@ -144,6 +142,7 @@ export function compileSlotSchema(company, sequenceSlots, options = {}) {
144
142
  }
145
143
  fields[fieldName] = toRuntimeField(fieldDef, options.functions);
146
144
  }
145
+ Object.assign(fields, PLATFORM_SESSION_FIELDS);
147
146
  requireRowIdField(fields, formatFieldPath('session', ROW_ID_FIELD), issues);
148
147
  tables.session = {
149
148
  label: tableView.label,
@@ -0,0 +1,38 @@
1
+ import type { RuntimeTableDef } from './types.js';
2
+ export declare const PLATFORM_SESSION_FIELDS: {
3
+ readonly is_inbound_call: {
4
+ readonly derived: false;
5
+ readonly label: 'Inbound call';
6
+ readonly dataType: 'boolean';
7
+ readonly source: 'system';
8
+ readonly extraction: 'Set by the conversation entry pipeline';
9
+ readonly enum: null;
10
+ readonly nullable: false;
11
+ readonly identifier: null;
12
+ readonly ref: null;
13
+ };
14
+ readonly is_first_call: {
15
+ readonly derived: false;
16
+ readonly label: 'First call';
17
+ readonly dataType: 'boolean';
18
+ readonly source: 'system';
19
+ readonly extraction: 'No prior session for this case contact';
20
+ readonly enum: null;
21
+ readonly nullable: false;
22
+ readonly identifier: null;
23
+ readonly ref: null;
24
+ };
25
+ readonly is_new_user: {
26
+ readonly derived: false;
27
+ readonly label: 'New user';
28
+ readonly dataType: 'boolean';
29
+ readonly source: 'system';
30
+ readonly extraction: 'No existing contact for this party';
31
+ readonly enum: null;
32
+ readonly nullable: false;
33
+ readonly identifier: null;
34
+ readonly ref: null;
35
+ };
36
+ };
37
+ export declare function createPlatformSessionTable(): RuntimeTableDef;
38
+ //# sourceMappingURL=platform-session-fields.d.ts.map
@@ -0,0 +1,48 @@
1
+ import { idField } from './schema.js';
2
+ export const PLATFORM_SESSION_FIELDS = {
3
+ is_inbound_call: {
4
+ derived: false,
5
+ label: 'Inbound call',
6
+ dataType: 'boolean',
7
+ source: 'system',
8
+ extraction: 'Set by the conversation entry pipeline',
9
+ enum: null,
10
+ nullable: false,
11
+ identifier: null,
12
+ ref: null,
13
+ },
14
+ is_first_call: {
15
+ derived: false,
16
+ label: 'First call',
17
+ dataType: 'boolean',
18
+ source: 'system',
19
+ extraction: 'No prior session for this case contact',
20
+ enum: null,
21
+ nullable: false,
22
+ identifier: null,
23
+ ref: null,
24
+ },
25
+ is_new_user: {
26
+ derived: false,
27
+ label: 'New user',
28
+ dataType: 'boolean',
29
+ source: 'system',
30
+ extraction: 'No existing contact for this party',
31
+ enum: null,
32
+ nullable: false,
33
+ identifier: null,
34
+ ref: null,
35
+ },
36
+ };
37
+ export function createPlatformSessionTable() {
38
+ return {
39
+ label: 'Session',
40
+ rows: 'single',
41
+ description: 'Per-conversation session fields',
42
+ fields: {
43
+ id: { ...idField, ref: null },
44
+ ...PLATFORM_SESSION_FIELDS,
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=platform-session-fields.js.map
@@ -82,8 +82,8 @@ export type SessionTableDef = {
82
82
  fields: Record<string, NormalFieldCore>;
83
83
  };
84
84
  export type SequenceSlots = {
85
- [table: string]: SequenceCompanyTableView | SessionTableDef;
86
- session: SessionTableDef;
85
+ [table: string]: SequenceCompanyTableView | SessionTableDef | undefined;
86
+ session?: SessionTableDef;
87
87
  };
88
88
  /** Effective field shape used for Slots codegen. */
89
89
  export type EffectiveFieldDef = {
@@ -33,6 +33,8 @@ export type OverlayExecuteMessage = {
33
33
  runToken?: string;
34
34
  /** Logger request id for `ctx.api` RPC; not the overlay execute correlation id. */
35
35
  logRequestId?: string;
36
+ /** Logger tags inherited from the backend execution context. */
37
+ logTags?: string[];
36
38
  };
37
39
  export type OverlayExecuteResultMessage = {
38
40
  type: 'execute.result';
@@ -3,7 +3,7 @@ export { buildActionContext, type BuildActionContextOptions } from './build-cont
3
3
  export { resolveSystemFnParams } from './system-args.js';
4
4
  export { createFakeApiHost, type FakeApiHostOptions } from './fake/index.js';
5
5
  export { defaultPlatformApis, emptyIntegration, type PlatformApiOverrides } from './fake/empty-api.js';
6
- export { createRpcApiHost, REQUEST_ID_HEADER, readRequestIdHeader } from './rpc/index.js';
6
+ export { createRpcApiHost, LOG_TAGS_HEADER, REQUEST_ID_HEADER, encodeLogTagsHeader, readLogTagsHeader, readRequestIdHeader, } from './rpc/index.js';
7
7
  export { bindLogMeta, noopLog } from './log.js';
8
8
  export { makeCtx, makeCtxAsync } from './make-ctx.js';
9
9
  export { defaultHttpApi } from '../core/context/http.js';
@@ -2,7 +2,7 @@ export { buildActionContext } from './build-context.js';
2
2
  export { resolveSystemFnParams } from './system-args.js';
3
3
  export { createFakeApiHost } from './fake/index.js';
4
4
  export { defaultPlatformApis, emptyIntegration } from './fake/empty-api.js';
5
- export { createRpcApiHost, REQUEST_ID_HEADER, readRequestIdHeader } from './rpc/index.js';
5
+ export { createRpcApiHost, LOG_TAGS_HEADER, REQUEST_ID_HEADER, encodeLogTagsHeader, readLogTagsHeader, readRequestIdHeader, } from './rpc/index.js';
6
6
  export { bindLogMeta, noopLog } from './log.js';
7
7
  export { makeCtx, makeCtxAsync } from './make-ctx.js';
8
8
  export { defaultHttpApi } from '../core/context/http.js';
@@ -6,5 +6,5 @@ export { createListBindingsProcedure } from './integration/list-bindings.js';
6
6
  export { createPlatformRouter, type PlatformInvokeHandler } from './platform.js';
7
7
  export { createLogRouter, type LogEmitHandler } from './log.js';
8
8
  export { createRpcApiHost } from './trpc-client.js';
9
- export { REQUEST_ID_HEADER, readRequestIdHeader } from './request-id.js';
9
+ export { LOG_TAGS_HEADER, REQUEST_ID_HEADER, encodeLogTagsHeader, readLogTagsHeader, readRequestIdHeader, } from './request-id.js';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -5,5 +5,5 @@ export { createListBindingsProcedure } from './integration/list-bindings.js';
5
5
  export { createPlatformRouter } from './platform.js';
6
6
  export { createLogRouter } from './log.js';
7
7
  export { createRpcApiHost } from './trpc-client.js';
8
- export { REQUEST_ID_HEADER, readRequestIdHeader } from './request-id.js';
8
+ export { LOG_TAGS_HEADER, REQUEST_ID_HEADER, encodeLogTagsHeader, readLogTagsHeader, readRequestIdHeader, } from './request-id.js';
9
9
  //# sourceMappingURL=index.js.map
@@ -8,11 +8,13 @@ export declare const logEmitInput: z.ZodObject<{
8
8
  }>;
9
9
  message: z.ZodString;
10
10
  extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
11
12
  }, z.core.$strip>;
12
13
  export type LogEmitHandler = (input: {
13
14
  level: 'info' | 'warn' | 'error';
14
15
  message: string;
15
16
  extra?: Record<string, unknown>;
17
+ tags?: string[];
16
18
  ctx: RpcContext;
17
19
  }) => Promise<void>;
18
20
  export declare function createLogRouter(emit: LogEmitHandler): import("@trpc/server").TRPCBuiltRouter<{
@@ -26,6 +28,7 @@ export declare function createLogRouter(emit: LogEmitHandler): import("@trpc/ser
26
28
  level: "error" | "info" | "warn";
27
29
  message: string;
28
30
  extra?: Record<string, unknown> | undefined;
31
+ tags?: string[] | undefined;
29
32
  };
30
33
  output: {
31
34
  ok: true;
@@ -4,11 +4,12 @@ export const logEmitInput = z.object({
4
4
  level: z.enum(['info', 'warn', 'error']),
5
5
  message: z.string(),
6
6
  extra: z.record(z.string(), z.unknown()).optional(),
7
+ tags: z.array(z.string()).optional(),
7
8
  });
8
9
  export function createLogRouter(emit) {
9
10
  return router({
10
11
  emit: publicProcedure.input(logEmitInput).mutation(async ({ ctx, input }) => {
11
- await emit({ level: input.level, message: input.message, extra: input.extra, ctx });
12
+ await emit({ level: input.level, message: input.message, extra: input.extra, tags: input.tags, ctx });
12
13
  return { ok: true };
13
14
  }),
14
15
  });
@@ -1,5 +1,10 @@
1
1
  export declare const REQUEST_ID_HEADER = "x-request-id";
2
+ export declare const LOG_TAGS_HEADER = "x-superpanel-log-tags";
2
3
  export declare function readRequestIdHeader(headers: {
3
4
  get(name: string): string | null;
4
5
  } | Record<string, string | string[] | undefined>): string | undefined;
6
+ export declare function encodeLogTagsHeader(tags: string[]): string;
7
+ export declare function readLogTagsHeader(headers: {
8
+ get(name: string): string | null;
9
+ }): string[] | undefined;
5
10
  //# sourceMappingURL=request-id.d.ts.map
@@ -1,4 +1,5 @@
1
1
  export const REQUEST_ID_HEADER = 'x-request-id';
2
+ export const LOG_TAGS_HEADER = 'x-superpanel-log-tags';
2
3
  function firstString(value) {
3
4
  const raw = Array.isArray(value) ? value[0] : value;
4
5
  return typeof raw === 'string' && raw.length > 0 ? raw : undefined;
@@ -10,4 +11,21 @@ export function readRequestIdHeader(headers) {
10
11
  const record = headers;
11
12
  return firstString(record[REQUEST_ID_HEADER]);
12
13
  }
14
+ export function encodeLogTagsHeader(tags) {
15
+ return JSON.stringify(tags);
16
+ }
17
+ export function readLogTagsHeader(headers) {
18
+ const raw = headers.get(LOG_TAGS_HEADER);
19
+ if (!raw)
20
+ return undefined;
21
+ try {
22
+ const parsed = JSON.parse(raw);
23
+ if (!Array.isArray(parsed) || !parsed.every((tag) => typeof tag === 'string'))
24
+ return undefined;
25
+ return parsed;
26
+ }
27
+ catch {
28
+ return undefined;
29
+ }
30
+ }
13
31
  //# sourceMappingURL=request-id.js.map
@@ -3,5 +3,7 @@ export declare function createRpcApiHost(options: {
3
3
  baseUrl: string;
4
4
  getToken: () => string | Promise<string>;
5
5
  getRequestId?: () => string | undefined;
6
+ getTags?: () => string[] | undefined;
7
+ waitUntil?: (promise: Promise<unknown>) => void;
6
8
  }): ApiHost;
7
9
  //# sourceMappingURL=trpc-client.d.ts.map
@@ -4,9 +4,15 @@ import { defaultHttpApi } from '../../core/context/http.js';
4
4
  import { integrationSurfaceKeys, } from '../../core/context/types.js';
5
5
  import { bindEnvService } from '../../core/context/env.js';
6
6
  import { REQUEST_ID_HEADER } from './request-id.js';
7
- function rpcLogger(c) {
7
+ function rpcLogger(c, getTags, waitUntil) {
8
8
  const emit = (level, message, extra) => {
9
- void c.log.emit.mutate({ level, message, extra }).catch(() => { });
9
+ const pending = c.log.emit.mutate({ level, message, extra, tags: getTags?.() }).catch(() => { });
10
+ if (waitUntil) {
11
+ waitUntil(pending);
12
+ }
13
+ else {
14
+ void pending;
15
+ }
10
16
  };
11
17
  return {
12
18
  info: (message, extra) => emit('info', message, extra),
@@ -100,7 +106,7 @@ export function createRpcApiHost(options) {
100
106
  return {
101
107
  ...buildPlatformApis(c),
102
108
  integration: buildSurfaces(c, metas),
103
- log: rpcLogger(c),
109
+ log: rpcLogger(c, options.getTags, options.waitUntil),
104
110
  http: defaultHttpApi(),
105
111
  };
106
112
  },
@@ -72,6 +72,7 @@ export declare function createAppRouter(modules: {
72
72
  level: "error" | "info" | "warn";
73
73
  message: string;
74
74
  extra?: Record<string, unknown> | undefined;
75
+ tags?: string[] | undefined;
75
76
  };
76
77
  output: {
77
78
  ok: true;
package/dist/index.d.ts CHANGED
@@ -30,7 +30,7 @@ export { loadSequenceCaseContextView, loadSequenceFunctions } from './builder/lo
30
30
  export { findTsModule } from './builder/paths.js';
31
31
  export type { OverlayClientMessage, OverlayExecuteMessage, OverlayExecuteResultMessage, OverlayAuthErrorMessage, OverlayAuthMessage, OverlayAuthOkMessage, OverlayMessage, OverlayPushMessage, OverlayReplacedMessage, OverlayServerMessage, } from './dev-overlay/protocol.js';
32
32
  export { encodeOverlayMessage, OVERLAY_REPLACED_CLOSE_CODE, parseOverlayMessage } from './dev-overlay/protocol.js';
33
- export { buildActionContext, bindLogMeta, createFakeApiHost, defaultPlatformApis, emptyIntegration, createRpcApiHost, REQUEST_ID_HEADER, readRequestIdHeader, makeCtx, makeCtxAsync, noopLog, type ActionContext, type ActionDataSlice, type ApiHost, type FakeApiHostOptions, type RunScope, } from './fn-context/index.js';
33
+ export { buildActionContext, bindLogMeta, createFakeApiHost, defaultPlatformApis, emptyIntegration, createRpcApiHost, LOG_TAGS_HEADER, REQUEST_ID_HEADER, encodeLogTagsHeader, readLogTagsHeader, readRequestIdHeader, makeCtx, makeCtxAsync, noopLog, type ActionContext, type ActionDataSlice, type ApiHost, type FakeApiHostOptions, type RunScope, } from './fn-context/index.js';
34
34
  export { createAppRouter, createIntegrationRouter, createListBindingsProcedure, createLogRouter, createPlatformRouter, isRpcCodedError, parseScriptInput, ScriptInputError, type AppRouter, type RpcCodedError, type RpcErrorCode, type IntegrationInvokeHandler, type LogEmitHandler, type PlatformInvokeHandler, type RpcContext, } from './fn-context/rpc/index.js';
35
35
  export * from './compute-host/index.js';
36
36
  export { defineBoolComputeFunc, defineComputeFunc } from './core/functions/define/compute.js';
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ export { compileSequenceAgendas, fatalAgendaIssues } from './builder/compile/com
19
19
  export { loadSequenceCaseContextView, loadSequenceFunctions } from './builder/load.js';
20
20
  export { findTsModule } from './builder/paths.js';
21
21
  export { encodeOverlayMessage, OVERLAY_REPLACED_CLOSE_CODE, parseOverlayMessage } from './dev-overlay/protocol.js';
22
- export { buildActionContext, bindLogMeta, createFakeApiHost, defaultPlatformApis, emptyIntegration, createRpcApiHost, REQUEST_ID_HEADER, readRequestIdHeader, makeCtx, makeCtxAsync, noopLog, } from './fn-context/index.js';
22
+ export { buildActionContext, bindLogMeta, createFakeApiHost, defaultPlatformApis, emptyIntegration, createRpcApiHost, LOG_TAGS_HEADER, REQUEST_ID_HEADER, encodeLogTagsHeader, readLogTagsHeader, readRequestIdHeader, makeCtx, makeCtxAsync, noopLog, } from './fn-context/index.js';
23
23
  export { createAppRouter, createIntegrationRouter, createListBindingsProcedure, createLogRouter, createPlatformRouter, isRpcCodedError, parseScriptInput, ScriptInputError, } from './fn-context/rpc/index.js';
24
24
  export * from './compute-host/index.js';
25
25
  export { defineBoolComputeFunc, defineComputeFunc } from './core/functions/define/compute.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superpanel-sdk/runtime",
3
- "version": "0.0.1-internal.2",
3
+ "version": "0.2.1",
4
4
  "description": "Slot + Stage runtime: schema, writes, derived recompute, agenda compile/walk/simulate",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",