@xemahq/agent-session-runtime 0.11.1 → 0.11.2
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 +2 -3
- package/src/index.ts +0 -36
- package/src/lib/agent-resolution.ts +0 -557
- package/src/lib/agent-workspace-manifest.ts +0 -632
- package/src/lib/composer.ts +0 -1315
- package/src/lib/dispatch-contract.ts +0 -151
- package/src/lib/drift-detector.ts +0 -497
- package/src/lib/environment-resolver.ts +0 -480
- package/src/lib/errors.ts +0 -43
- package/src/lib/launch-identity/canonical-contract.ts +0 -352
- package/src/lib/launch-identity/index.ts +0 -4
- package/src/lib/launch-identity/runtime-template-key.ts +0 -143
- package/src/lib/launch-identity/session-binding.ts +0 -152
- package/src/lib/launch-identity/thread-reuse-key.ts +0 -93
- package/src/lib/lifecycle-state.ts +0 -30
- package/src/lib/skill-bundle-template-resolver.ts +0 -147
- package/src/lib/types.ts +0 -453
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
canonicalContractJson,
|
|
3
|
-
hashCanonicalContract,
|
|
4
|
-
type ResourceBindingRef,
|
|
5
|
-
requireEnumValue,
|
|
6
|
-
requireExactObject,
|
|
7
|
-
requireNonEmptyString,
|
|
8
|
-
requireResourceBindingRefs,
|
|
9
|
-
requireSha256,
|
|
10
|
-
} from './canonical-contract';
|
|
11
|
-
|
|
12
|
-
export enum ThreadReusePolicy {
|
|
13
|
-
ExplicitlyShareable = 'explicitly-shareable',
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ThreadReuseKey {
|
|
17
|
-
readonly schemaVersion: 1;
|
|
18
|
-
readonly reusePolicy: ThreadReusePolicy.ExplicitlyShareable;
|
|
19
|
-
readonly organizationId: string;
|
|
20
|
-
readonly projectId: string;
|
|
21
|
-
readonly userId: string;
|
|
22
|
-
readonly runtimeTemplateHash: string;
|
|
23
|
-
readonly conversationRef: string;
|
|
24
|
-
readonly workspaceRef: string;
|
|
25
|
-
readonly domainRefs: readonly ResourceBindingRef[];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const REQUIRED_KEYS = [
|
|
29
|
-
'schemaVersion',
|
|
30
|
-
'reusePolicy',
|
|
31
|
-
'organizationId',
|
|
32
|
-
'projectId',
|
|
33
|
-
'userId',
|
|
34
|
-
'runtimeTemplateHash',
|
|
35
|
-
'conversationRef',
|
|
36
|
-
'workspaceRef',
|
|
37
|
-
'domainRefs',
|
|
38
|
-
] as const;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Canonical identity for the deliberately narrower same-user conversation and
|
|
42
|
-
* filesystem reuse decision. A RuntimeTemplateKey match alone never permits
|
|
43
|
-
* Thread reuse.
|
|
44
|
-
*/
|
|
45
|
-
export function createThreadReuseKey(input: unknown): ThreadReuseKey {
|
|
46
|
-
const object = requireExactObject(input, 'ThreadReuseKey', REQUIRED_KEYS);
|
|
47
|
-
|
|
48
|
-
if (object.schemaVersion !== 1) {
|
|
49
|
-
throw new TypeError('ThreadReuseKey.schemaVersion must be 1.');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return Object.freeze({
|
|
53
|
-
schemaVersion: 1,
|
|
54
|
-
reusePolicy: requireEnumValue(
|
|
55
|
-
object.reusePolicy,
|
|
56
|
-
'ThreadReuseKey.reusePolicy',
|
|
57
|
-
[ThreadReusePolicy.ExplicitlyShareable],
|
|
58
|
-
),
|
|
59
|
-
organizationId: requireNonEmptyString(
|
|
60
|
-
object.organizationId,
|
|
61
|
-
'ThreadReuseKey.organizationId',
|
|
62
|
-
),
|
|
63
|
-
projectId: requireNonEmptyString(
|
|
64
|
-
object.projectId,
|
|
65
|
-
'ThreadReuseKey.projectId',
|
|
66
|
-
),
|
|
67
|
-
userId: requireNonEmptyString(object.userId, 'ThreadReuseKey.userId'),
|
|
68
|
-
runtimeTemplateHash: requireSha256(
|
|
69
|
-
object.runtimeTemplateHash,
|
|
70
|
-
'ThreadReuseKey.runtimeTemplateHash',
|
|
71
|
-
),
|
|
72
|
-
conversationRef: requireNonEmptyString(
|
|
73
|
-
object.conversationRef,
|
|
74
|
-
'ThreadReuseKey.conversationRef',
|
|
75
|
-
),
|
|
76
|
-
workspaceRef: requireNonEmptyString(
|
|
77
|
-
object.workspaceRef,
|
|
78
|
-
'ThreadReuseKey.workspaceRef',
|
|
79
|
-
),
|
|
80
|
-
domainRefs: requireResourceBindingRefs(
|
|
81
|
-
object.domainRefs,
|
|
82
|
-
'ThreadReuseKey.domainRefs',
|
|
83
|
-
),
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function serializeThreadReuseKey(input: ThreadReuseKey): string {
|
|
88
|
-
return canonicalContractJson(createThreadReuseKey(input));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function hashThreadReuseKey(input: ThreadReuseKey): string {
|
|
92
|
-
return hashCanonicalContract(createThreadReuseKey(input));
|
|
93
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
2
|
-
// ── Agent-session lifecycle state machine — re-export of the kernel SSOT ──
|
|
3
|
-
//
|
|
4
|
-
// This file is a thin re-export surface. The closed `SessionLifecycleState` /
|
|
5
|
-
// `SessionOwnerKind` value sets, the transition FSM (`canTransition`), and the
|
|
6
|
-
// `isTerminal` / `isPausable` / `isResumable` predicates are the canonical
|
|
7
|
-
// Layer-0 contract owned by `@xemahq/kernel-contracts/agent-session`. The former
|
|
8
|
-
// hand-maintained copy that lived here was collapsed into that single source of
|
|
9
|
-
// truth; this module is retained ONLY so the package's public surface
|
|
10
|
-
// (re-exported from `src/index.ts`) is unchanged.
|
|
11
|
-
//
|
|
12
|
-
// Prisma cannot import a TS value, so the agent-session-api schema re-declares
|
|
13
|
-
// the same members and CI guards parity
|
|
14
|
-
// (`tooling/boundaries/check-session-enum-parity.mjs`).
|
|
15
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
SessionLifecycleState,
|
|
19
|
-
SessionOwnerKind,
|
|
20
|
-
canTransition,
|
|
21
|
-
isTerminal,
|
|
22
|
-
isPausable,
|
|
23
|
-
isResumable,
|
|
24
|
-
SessionLifecycleStateSchema,
|
|
25
|
-
SessionOwnerKindSchema,
|
|
26
|
-
} from '@xemahq/kernel-contracts/agent-session';
|
|
27
|
-
export type {
|
|
28
|
-
SessionLifecycleStateValue,
|
|
29
|
-
SessionOwnerKindValue,
|
|
30
|
-
} from '@xemahq/kernel-contracts/agent-session';
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
2
|
-
// ── Skill-bundle-backed TemplateResolver ──
|
|
3
|
-
//
|
|
4
|
-
// Seed-file templates used to
|
|
5
|
-
// live in `workspace-manifests-api` (the `workspace_manifest_templates` table)
|
|
6
|
-
// and were fetched by name. They are now SKILL-BUNDLE RESOURCES served by
|
|
7
|
-
// `skill-registry-api` (`GET /skills/bundle`): a biome that ships templates
|
|
8
|
-
// packages them inside a skill bundle under `assets/templates/<name>.hbs`.
|
|
9
|
-
//
|
|
10
|
-
// This factory builds a `TemplateResolver` that:
|
|
11
|
-
// 1. Walks the resolved composition's skill set.
|
|
12
|
-
// 2. Fetches each skill bundle through the injected `fetchBundle` function.
|
|
13
|
-
// 3. Locates the requested template by mapping the bare template name
|
|
14
|
-
// (`demo-seeded-canvas-index.html`) to the resource relPath
|
|
15
|
-
// (`assets/templates/demo-seeded-canvas-index.html.hbs`).
|
|
16
|
-
// 4. Compiles the raw template via the injected `compileTemplate` function
|
|
17
|
-
// and renders it with the seed-file `vars`.
|
|
18
|
-
//
|
|
19
|
-
// Both the bundle-fetch and the Handlebars compile are INJECTED so this
|
|
20
|
-
// Kernel package stays free of an HTTP client and a templating dependency —
|
|
21
|
-
// `agent-session-api` (and, after Step 4, `workflow-runtime-worker`) supply
|
|
22
|
-
// the concrete implementations and share this one resolution algorithm.
|
|
23
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
24
|
-
|
|
25
|
-
import type { TemplateResolver } from './types';
|
|
26
|
-
|
|
27
|
-
/** The `assets/templates/` directory prefix every template resource sits under. */
|
|
28
|
-
const TEMPLATE_RESOURCE_PREFIX = 'assets/templates/';
|
|
29
|
-
/** The file extension a Handlebars template resource carries inside the bundle. */
|
|
30
|
-
const TEMPLATE_RESOURCE_SUFFIX = '.hbs';
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* One resource inside a skill bundle. Mirrors `SkillBundleResourceDto` from
|
|
34
|
-
* the skill-registry-api client without importing it (Kernel stays
|
|
35
|
-
* client-dep-free).
|
|
36
|
-
*/
|
|
37
|
-
export interface SkillBundleResource {
|
|
38
|
-
/** Forward-slash path relative to the skill directory. */
|
|
39
|
-
readonly relPath: string;
|
|
40
|
-
/** File bytes, base64-encoded. */
|
|
41
|
-
readonly content: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* The slice of a skill bundle this resolver needs. Mirrors
|
|
46
|
-
* `SkillBundleResponseDto` (subset).
|
|
47
|
-
*/
|
|
48
|
-
export interface SkillBundle {
|
|
49
|
-
readonly slug: string;
|
|
50
|
-
readonly resources: readonly SkillBundleResource[];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Fetches one skill bundle by slug. Implemented by the consumer with its
|
|
55
|
-
* `skill-registry-api` Orval client. Must reject (not return null) on a
|
|
56
|
-
* missing bundle — a template referencing a skill that does not resolve is
|
|
57
|
-
* a fail-fast condition.
|
|
58
|
-
*/
|
|
59
|
-
export type SkillBundleFetcher = (slug: string) => Promise<SkillBundle>;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Compiles a raw template string and renders it with `vars`. Injected so
|
|
63
|
-
* the Kernel package does not depend on a concrete templating library.
|
|
64
|
-
*/
|
|
65
|
-
export type TemplateCompiler = (
|
|
66
|
-
source: string,
|
|
67
|
-
vars: Readonly<Record<string, unknown>>,
|
|
68
|
-
) => string;
|
|
69
|
-
|
|
70
|
-
/** Raised when a referenced seed-file template cannot be resolved. */
|
|
71
|
-
export class SkillBundleTemplateNotFoundError extends Error {
|
|
72
|
-
constructor(
|
|
73
|
-
public readonly templateName: string,
|
|
74
|
-
public readonly skillSlugs: readonly string[],
|
|
75
|
-
) {
|
|
76
|
-
super(
|
|
77
|
-
`Seed-file template "${templateName}" was not found as ` +
|
|
78
|
-
`"${TEMPLATE_RESOURCE_PREFIX}${templateName}${TEMPLATE_RESOURCE_SUFFIX}" ` +
|
|
79
|
-
`in any of the composition's skill bundles ` +
|
|
80
|
-
`[${skillSlugs.join(', ') || '<none>'}]. The biome that owns the ` +
|
|
81
|
-
`template must ship it inside a skill bundle the composition references.`,
|
|
82
|
-
);
|
|
83
|
-
this.name = 'SkillBundleTemplateNotFoundError';
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Map a bare seed-file template name to its skill-bundle resource relPath.
|
|
89
|
-
* `demo-seeded-canvas-index.html` → `assets/templates/demo-seeded-canvas-index.html.hbs`.
|
|
90
|
-
*/
|
|
91
|
-
export function templateResourceRelPath(templateName: string): string {
|
|
92
|
-
return `${TEMPLATE_RESOURCE_PREFIX}${templateName}${TEMPLATE_RESOURCE_SUFFIX}`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Build a `TemplateResolver` backed by the resolved composition's skill
|
|
97
|
-
* bundles.
|
|
98
|
-
*
|
|
99
|
-
* `skillSlugs` is the set of skill slugs attached to the resolved
|
|
100
|
-
* composition (root node + descendants). Bundles are fetched lazily and
|
|
101
|
-
* memoised for the lifetime of the returned resolver, so a session whose
|
|
102
|
-
* manifest references three templates from one skill fetches that bundle
|
|
103
|
-
* exactly once.
|
|
104
|
-
*
|
|
105
|
-
* Fail-fast: a `fetchBundle` rejection propagates; a template name that
|
|
106
|
-
* matches no resource in any bundle throws `SkillBundleTemplateNotFoundError`.
|
|
107
|
-
*/
|
|
108
|
-
export function buildSkillBundleTemplateResolver(params: {
|
|
109
|
-
readonly skillSlugs: readonly string[];
|
|
110
|
-
readonly fetchBundle: SkillBundleFetcher;
|
|
111
|
-
readonly compileTemplate: TemplateCompiler;
|
|
112
|
-
}): TemplateResolver {
|
|
113
|
-
const { skillSlugs, fetchBundle, compileTemplate } = params;
|
|
114
|
-
// De-duplicate so the same skill referenced at multiple nodes is fetched once.
|
|
115
|
-
const uniqueSlugs = [...new Set(skillSlugs)];
|
|
116
|
-
const bundleCache = new Map<string, Promise<SkillBundle>>();
|
|
117
|
-
|
|
118
|
-
const loadBundle = (slug: string): Promise<SkillBundle> => {
|
|
119
|
-
const cached = bundleCache.get(slug);
|
|
120
|
-
if (cached) {
|
|
121
|
-
return cached;
|
|
122
|
-
}
|
|
123
|
-
const pending = fetchBundle(slug);
|
|
124
|
-
bundleCache.set(slug, pending);
|
|
125
|
-
return pending;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
async resolve(
|
|
130
|
-
name: string,
|
|
131
|
-
vars: Readonly<Record<string, unknown>>,
|
|
132
|
-
): Promise<string> {
|
|
133
|
-
const relPath = templateResourceRelPath(name);
|
|
134
|
-
for (const slug of uniqueSlugs) {
|
|
135
|
-
const bundle = await loadBundle(slug);
|
|
136
|
-
const resource = bundle.resources.find((r) => r.relPath === relPath);
|
|
137
|
-
if (resource) {
|
|
138
|
-
const source = Buffer.from(resource.content, 'base64').toString(
|
|
139
|
-
'utf8',
|
|
140
|
-
);
|
|
141
|
-
return compileTemplate(source, vars);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
throw new SkillBundleTemplateNotFoundError(name, uniqueSlugs);
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
}
|