@vibesdotdev/session 1.0.0-rc.1 → 1.0.0-rc.3
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/dist/admission/admit-caller.context.descriptor.d.ts +33 -0
- package/dist/admission/admit-caller.context.descriptor.d.ts.map +1 -0
- package/dist/admission/admit-caller.context.descriptor.js +10 -0
- package/dist/admission/admit-caller.context.descriptor.js.map +1 -0
- package/dist/admission/admit-caller.context.impl.d.ts +8 -0
- package/dist/admission/admit-caller.context.impl.d.ts.map +1 -0
- package/dist/admission/admit-caller.context.impl.js +15 -0
- package/dist/admission/admit-caller.context.impl.js.map +1 -0
- package/dist/admission/admit-caller.d.ts +57 -0
- package/dist/admission/admit-caller.d.ts.map +1 -0
- package/dist/admission/admit-caller.js +163 -0
- package/dist/admission/admit-caller.js.map +1 -0
- package/dist/cli/services/session/sessions.d.ts +4 -4
- package/dist/cli/services/session.cli.consumer.d.ts +1 -1
- package/dist/events/session.message-arrived.event.descriptor.d.ts +34 -0
- package/dist/events/session.message-arrived.event.descriptor.d.ts.map +1 -0
- package/dist/events/session.message-arrived.event.descriptor.js +36 -0
- package/dist/events/session.message-arrived.event.descriptor.js.map +1 -0
- package/dist/manager.d.ts +99 -2
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +431 -3
- package/dist/manager.js.map +1 -1
- package/dist/mcp/schemas/tools.d.ts +3 -0
- package/dist/mcp/schemas/tools.d.ts.map +1 -1
- package/dist/mcp/schemas/tools.js +15 -2
- package/dist/mcp/schemas/tools.js.map +1 -1
- package/dist/mcp/utils/participant.d.ts +25 -8
- package/dist/mcp/utils/participant.d.ts.map +1 -1
- package/dist/mcp/utils/participant.js +26 -35
- package/dist/mcp/utils/participant.js.map +1 -1
- package/dist/schemas/index.d.ts +2 -2
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/participant.d.ts +30 -0
- package/dist/schemas/participant.d.ts.map +1 -1
- package/dist/schemas/participant.js +38 -1
- package/dist/schemas/participant.js.map +1 -1
- package/dist/schemas/session.d.ts +5 -5
- package/dist/schemas/session.js +1 -1
- package/dist/schemas/session.js.map +1 -1
- package/dist/session.plugin.d.ts.map +1 -1
- package/dist/session.plugin.js +5 -0
- package/dist/session.plugin.js.map +1 -1
- package/dist/storage/session-connections.record.descriptor.d.ts +9 -0
- package/dist/storage/session-connections.record.descriptor.d.ts.map +1 -1
- package/dist/storage/session-connections.record.descriptor.js +23 -2
- package/dist/storage/session-connections.record.descriptor.js.map +1 -1
- package/dist/storage/session-sessions.record.descriptor.d.ts +1 -1
- package/dist/tools/lifecycle/context/handler.d.ts +1 -1
- package/dist/tools/lifecycle/init/handler.d.ts.map +1 -1
- package/dist/tools/lifecycle/init/handler.js +16 -0
- package/dist/tools/lifecycle/init/handler.js.map +1 -1
- package/dist/tools/lifecycle/init/schemas.d.ts +7 -0
- package/dist/tools/lifecycle/init/schemas.d.ts.map +1 -1
- package/dist/tools/lifecycle/init/schemas.js +14 -1
- package/dist/tools/lifecycle/init/schemas.js.map +1 -1
- package/dist/tools/lifecycle/init/types.d.ts +6 -0
- package/dist/tools/lifecycle/init/types.d.ts.map +1 -1
- package/dist/tools/lifecycle/init/types.js.map +1 -1
- package/dist/tools/lifecycle/packet/handler.d.ts +2 -2
- package/dist/tools/lifecycle/snapshot/handler.d.ts +1 -1
- package/dist/tools/lifecycle/state/status/handler.d.ts +1 -1
- package/dist/tools/lifecycle/tool/schemas/index.d.ts +3 -0
- package/dist/tools/lifecycle/tool/schemas/index.d.ts.map +1 -1
- package/dist/tools/lifecycle/tool/session.tool.descriptor.js +5 -5
- package/dist/tools/lifecycle/tool/session.tool.descriptor.js.map +1 -1
- package/dist/tools/lifecycle/tool/session.variant.init.impl.cloud.d.ts +2 -0
- package/dist/tools/lifecycle/tool/session.variant.init.impl.cloud.d.ts.map +1 -1
- package/dist/tools/lifecycle/tool/session.variant.init.impl.consumer.d.ts +2 -0
- package/dist/tools/lifecycle/tool/session.variant.init.impl.consumer.d.ts.map +1 -1
- package/dist/tools/lifecycle/tool/session.variant.update.impl.d.ts +1 -0
- package/dist/tools/lifecycle/tool/session.variant.update.impl.d.ts.map +1 -1
- package/dist/tools/lifecycle/update/handler.d.ts +2 -2
- package/dist/tools/lifecycle/update/handler.d.ts.map +1 -1
- package/dist/tools/lifecycle/update/handler.js +13 -0
- package/dist/tools/lifecycle/update/handler.js.map +1 -1
- package/dist/tools/lifecycle/update/schemas.d.ts +1 -0
- package/dist/tools/lifecycle/update/schemas.d.ts.map +1 -1
- package/dist/tools/lifecycle/update/schemas.js +3 -1
- package/dist/tools/lifecycle/update/schemas.js.map +1 -1
- package/dist/tools/messages/handlers.d.ts.map +1 -1
- package/dist/tools/messages/handlers.js +4 -2
- package/dist/tools/messages/handlers.js.map +1 -1
- package/dist/tools/messages/tool/session-collaborate.descriptor.js +1 -1
- package/dist/tools/messages/tool/session-collaborate.descriptor.js.map +1 -1
- package/dist/tools/scratchpad/tool/session-scratchpad.descriptor.js +4 -4
- package/dist/tools/scratchpad/tool/session-scratchpad.descriptor.js.map +1 -1
- package/dist/tools/todos/tool/session-todo.descriptor.js +3 -3
- package/dist/tools/todos/tool/session-todo.descriptor.js.map +1 -1
- package/dist/tools/workspace/tool/session-workspace.descriptor.js +1 -1
- package/dist/tools/workspace/tool/session-workspace.descriptor.js.map +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caller admission context descriptor (`session/admit-caller`).
|
|
3
|
+
*/
|
|
4
|
+
declare const _default: {
|
|
5
|
+
id: string;
|
|
6
|
+
kind: "context";
|
|
7
|
+
name?: string | undefined;
|
|
8
|
+
description?: string | undefined;
|
|
9
|
+
tags?: string[] | undefined;
|
|
10
|
+
hardware?: string[] | undefined;
|
|
11
|
+
enabled?: boolean | undefined;
|
|
12
|
+
priority?: number | undefined;
|
|
13
|
+
capabilityId?: string | undefined;
|
|
14
|
+
requiredContext?: string[] | undefined;
|
|
15
|
+
optionalContext?: string[] | undefined;
|
|
16
|
+
retention?: string | {
|
|
17
|
+
reason: string;
|
|
18
|
+
maxAgeDays?: number | undefined;
|
|
19
|
+
maxEntries?: number | undefined;
|
|
20
|
+
maxBytes?: number | undefined;
|
|
21
|
+
cascadeFrom?: string | undefined;
|
|
22
|
+
ageField?: string | undefined;
|
|
23
|
+
enforcedBy?: string | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
valueKind?: "data" | "service" | undefined;
|
|
26
|
+
valueSchema?: unknown;
|
|
27
|
+
config?: {
|
|
28
|
+
sources: ("literal" | "workspace" | "floor")[];
|
|
29
|
+
subset?: true | undefined;
|
|
30
|
+
} | undefined;
|
|
31
|
+
};
|
|
32
|
+
export default _default;
|
|
33
|
+
//# sourceMappingURL=admit-caller.context.descriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admit-caller.context.descriptor.d.ts","sourceRoot":"","sources":["../../src/admission/admit-caller.context.descriptor.ts"],"names":[],"mappings":"AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKH,wBAGG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caller admission context descriptor (`session/admit-caller`).
|
|
3
|
+
*/
|
|
4
|
+
import { createContextDescriptor } from '@vibesdotdev/kernel/factory/context';
|
|
5
|
+
import { ADMIT_CALLER_CONTEXT_ID } from '@vibesdotdev/kernel/schemas/invoke-caller';
|
|
6
|
+
export default createContextDescriptor({
|
|
7
|
+
id: ADMIT_CALLER_CONTEXT_ID,
|
|
8
|
+
description: 'Admit a tool call\'s caller: its running instance (and, for writes, its session) before the call runs.'
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=admit-caller.context.descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admit-caller.context.descriptor.js","sourceRoot":"","sources":["../../src/admission/admit-caller.context.descriptor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,eAAe,uBAAuB,CAAC;IACtC,EAAE,EAAE,uBAAuB;IAC3B,WAAW,EAAE,wGAAwG;CACrH,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type VibesRuntime } from '@vibesdotdev/kernel';
|
|
2
|
+
import type { AdmitCaller } from '@vibesdotdev/kernel/schemas/invoke-caller';
|
|
3
|
+
/** The admission function; the manager it uses belongs to the session runtime client. */
|
|
4
|
+
declare const defaultExport: {
|
|
5
|
+
provide: (runtime: VibesRuntime) => Promise<AdmitCaller>;
|
|
6
|
+
};
|
|
7
|
+
export default defaultExport;
|
|
8
|
+
//# sourceMappingURL=admit-caller.context.impl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admit-caller.context.impl.d.ts","sourceRoot":"","sources":["../../src/admission/admit-caller.context.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AAI7E,yFAAyF;AACzF,QAAA,MAAM,aAAa;uBACO,YAAY,KAAG,OAAO,CAAC,WAAW,CAAC;CAS5D,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {} from '@vibesdotdev/kernel';
|
|
2
|
+
import { getVibesClient } from '@vibesdotdev/kernel/client';
|
|
3
|
+
import { assertSessionRuntime } from "../client.js";
|
|
4
|
+
import { admitCaller, ToolSafetyFieldsSchema } from "./admit-caller.js";
|
|
5
|
+
/** The admission function; the manager it uses belongs to the session runtime client. */
|
|
6
|
+
const defaultExport = {
|
|
7
|
+
provide: async (runtime) => {
|
|
8
|
+
assertSessionRuntime(runtime);
|
|
9
|
+
const client = await getVibesClient('session', runtime);
|
|
10
|
+
const describeTool = (toolId) => ToolSafetyFieldsSchema.parse((runtime.hasKind('tools/tool') ? runtime.assets('tools/tool').descriptor(toolId) : undefined) ?? {});
|
|
11
|
+
return async (request) => admitCaller(await client.getManager(), request, describeTool);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export default defaultExport;
|
|
15
|
+
//# sourceMappingURL=admit-caller.context.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admit-caller.context.impl.js","sourceRoot":"","sources":["../../src/admission/admit-caller.context.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAsB,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAyB,MAAM,mBAAmB,CAAC;AAE/F,yFAAyF;AACzF,MAAM,aAAa,GAAG;IACrB,OAAO,EAAE,KAAK,EAAE,OAAqB,EAAwB,EAAE;QAC9D,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAgB,SAAS,EAAE,OAAO,CAAC,CAAC;QACvE,MAAM,YAAY,GAAG,CAAC,MAAc,EAAoB,EAAE,CACzD,sBAAsB,CAAC,KAAK,CAC3B,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CACnG,CAAC;QACH,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IACzF,CAAC;CACD,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caller admission: the one step every tool call takes before its invocation
|
|
3
|
+
* identity is fixed (`invokeTool`, tools/src/execution/invoke.ts). It gives the
|
|
4
|
+
* caller its running instance — one live row in the instance registry
|
|
5
|
+
* (`session.connections`) — whichever surface the call came through. How the
|
|
6
|
+
* caller arrived (MCP connection, daemon socket, in-process host) is read from
|
|
7
|
+
* the request as data and recorded on the instance; it never selects a path.
|
|
8
|
+
*/
|
|
9
|
+
import * as z from 'zod/v4';
|
|
10
|
+
import { type AdmitCallerRequest, type AdmittedCall } from '@vibesdotdev/kernel/schemas/invoke-caller';
|
|
11
|
+
import type { SessionManager } from '../manager/index.ts';
|
|
12
|
+
import type { RegisterInstanceInput } from '../schemas/index.ts';
|
|
13
|
+
/**
|
|
14
|
+
* The instance a call belongs to.
|
|
15
|
+
* - A declared `instanceId` is the instance.
|
|
16
|
+
* - An MCP connection is one instance per connection; its live transport touches it.
|
|
17
|
+
* - A harness conversation is one instance, keyed on (who, which conversation),
|
|
18
|
+
* across every host its calls run in; anything else is keyed on (this host,
|
|
19
|
+
* who). So two seats of one agent stay two instances. An in-process host
|
|
20
|
+
* keeps its seat open, so it hosts (heartbeats) the instance until it closes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function instanceFor(request: AdmitCallerRequest, hostKey: string): Omit<RegisterInstanceInput, 'clientName'> | undefined;
|
|
23
|
+
/** The tool fields that decide whether a call writes: its declared safety category, per action when declared. */
|
|
24
|
+
export declare const ToolSafetyFieldsSchema: z.ZodObject<{
|
|
25
|
+
safety: z.ZodCatch<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodPipe<z.ZodObject<{
|
|
26
|
+
category: z.ZodString;
|
|
27
|
+
}, z.core.$strip>, z.ZodTransform<string, {
|
|
28
|
+
category: string;
|
|
29
|
+
}>>]>>>;
|
|
30
|
+
schemas: z.ZodCatch<z.ZodOptional<z.ZodObject<{
|
|
31
|
+
actionSafety: z.ZodCatch<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
32
|
+
}, z.core.$strip>>>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
export type ToolSafetyFields = z.infer<typeof ToolSafetyFieldsSchema>;
|
|
35
|
+
/** The call input fields admission reads: the selected action and a named target session. */
|
|
36
|
+
declare const CallInputSchema: z.ZodObject<{
|
|
37
|
+
action: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
38
|
+
sessionId: z.ZodCatch<z.ZodOptional<z.ZodUUID>>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the call writes, by the platform's one rule (the same one host
|
|
42
|
+
* approval uses, external/src/harness/live-tools.ts): the selected action's
|
|
43
|
+
* declared safety, else the tool's; only a declared `read` is a read.
|
|
44
|
+
*/
|
|
45
|
+
export declare function callWrites(fields: ToolSafetyFields, input: z.infer<typeof CallInputSchema>): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Admit one call. Its instance is registered and kept alive. Its session is,
|
|
48
|
+
* in order: the session the caller already carries; the session the call names
|
|
49
|
+
* (`input.sessionId`, e.g. a message into a room); the session its instance is
|
|
50
|
+
* working in. A call that writes and still has no session gets one, owned by
|
|
51
|
+
* its participant. Membership follows authorization: only once the call
|
|
52
|
+
* succeeds does the instance take the lease and work in that session; a
|
|
53
|
+
* failed write archives the session it minted.
|
|
54
|
+
*/
|
|
55
|
+
export declare function admitCaller(manager: SessionManager, request: AdmitCallerRequest, describeTool: (toolId: string) => ToolSafetyFields): Promise<AdmittedCall>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=admit-caller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admit-caller.d.ts","sourceRoot":"","sources":["../../src/admission/admit-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAEN,KAAK,kBAAkB,EACvB,KAAK,YAAY,EAEjB,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAoBjE;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAC1B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,GACb,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,GAAG,SAAS,CA0BvD;AAED,iHAAiH;AACjH,eAAO,MAAM,sBAAsB;;;;;;;;;iBAMjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,6FAA6F;AAC7F,QAAA,MAAM,eAAe;;;iBAGnB,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,GAAG,OAAO,CAMpG;AAeD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAChC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,kBAAkB,EAC3B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,GAChD,OAAO,CAAC,YAAY,CAAC,CA8CvB"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caller admission: the one step every tool call takes before its invocation
|
|
3
|
+
* identity is fixed (`invokeTool`, tools/src/execution/invoke.ts). It gives the
|
|
4
|
+
* caller its running instance — one live row in the instance registry
|
|
5
|
+
* (`session.connections`) — whichever surface the call came through. How the
|
|
6
|
+
* caller arrived (MCP connection, daemon socket, in-process host) is read from
|
|
7
|
+
* the request as data and recorded on the instance; it never selects a path.
|
|
8
|
+
*/
|
|
9
|
+
import * as z from 'zod/v4';
|
|
10
|
+
import { sha256Hex } from '@vibesdotdev/shared/hashing';
|
|
11
|
+
import { RuntimeInvokeCallerSchema } from '@vibesdotdev/kernel/schemas/invoke-caller';
|
|
12
|
+
/** A metadata key that is absent, empty or not text carries nothing. */
|
|
13
|
+
const MetadataTextSchema = z.string().trim().min(1).optional().catch(undefined);
|
|
14
|
+
/** The call metadata admission reads: how the caller arrived. */
|
|
15
|
+
const AdmissionMetadataSchema = z.object({
|
|
16
|
+
'mcp.transportSessionId': MetadataTextSchema,
|
|
17
|
+
'mcp.connectionKey': MetadataTextSchema,
|
|
18
|
+
'mcp.transportMode': MetadataTextSchema,
|
|
19
|
+
'invoke.transport': MetadataTextSchema
|
|
20
|
+
});
|
|
21
|
+
/** A caller with no identity (an internal runtime call) is no one, and has no instance. */
|
|
22
|
+
function hasIdentity(caller, transportKey) {
|
|
23
|
+
return Boolean(transportKey || caller?.instanceId || caller?.participantId || caller?.agentId || caller?.harness);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The instance a call belongs to.
|
|
27
|
+
* - A declared `instanceId` is the instance.
|
|
28
|
+
* - An MCP connection is one instance per connection; its live transport touches it.
|
|
29
|
+
* - A harness conversation is one instance, keyed on (who, which conversation),
|
|
30
|
+
* across every host its calls run in; anything else is keyed on (this host,
|
|
31
|
+
* who). So two seats of one agent stay two instances. An in-process host
|
|
32
|
+
* keeps its seat open, so it hosts (heartbeats) the instance until it closes.
|
|
33
|
+
*/
|
|
34
|
+
export function instanceFor(request, hostKey) {
|
|
35
|
+
const metadata = AdmissionMetadataSchema.parse(request.metadata ?? {});
|
|
36
|
+
const caller = request.caller;
|
|
37
|
+
const mcpKey = metadata['mcp.transportSessionId'] ?? metadata['mcp.connectionKey'];
|
|
38
|
+
if (!hasIdentity(caller, mcpKey))
|
|
39
|
+
return undefined;
|
|
40
|
+
const mcpTransport = mcpKey ? `mcp-${metadata['mcp.transportMode'] ?? 'stdio'}` : undefined;
|
|
41
|
+
const transport = metadata['invoke.transport'] ?? mcpTransport ?? 'in-process';
|
|
42
|
+
const who = {
|
|
43
|
+
participantId: caller?.participantId,
|
|
44
|
+
agentId: caller?.agentId,
|
|
45
|
+
harness: caller?.harness,
|
|
46
|
+
harnessSessionId: caller?.harnessSessionId
|
|
47
|
+
};
|
|
48
|
+
if (caller?.instanceId)
|
|
49
|
+
return { instanceId: caller.instanceId, transport, ...who };
|
|
50
|
+
if (mcpKey)
|
|
51
|
+
return { instanceId: mcpKey, transport, ...who };
|
|
52
|
+
// One harness conversation is one instance whichever host its calls run in
|
|
53
|
+
// (each one-shot `vibes` run is its own host); without one, the host is the seat.
|
|
54
|
+
const seat = who.harnessSessionId
|
|
55
|
+
? ['harness', who.participantId ?? who.agentId ?? who.harness, who.harnessSessionId].join('|')
|
|
56
|
+
: [hostKey, who.participantId ?? who.agentId ?? who.harness].join('|');
|
|
57
|
+
return {
|
|
58
|
+
instanceId: `${transport}:${sha256Hex(seat).slice(0, 24)}`,
|
|
59
|
+
transport,
|
|
60
|
+
hosted: transport === 'in-process',
|
|
61
|
+
...who
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** The tool fields that decide whether a call writes: its declared safety category, per action when declared. */
|
|
65
|
+
export const ToolSafetyFieldsSchema = z.object({
|
|
66
|
+
safety: z
|
|
67
|
+
.union([z.string(), z.object({ category: z.string() }).transform((safety) => safety.category)])
|
|
68
|
+
.optional()
|
|
69
|
+
.catch(undefined),
|
|
70
|
+
schemas: z.object({ actionSafety: z.record(z.string(), z.string()).optional().catch(undefined) }).optional().catch(undefined)
|
|
71
|
+
});
|
|
72
|
+
/** The call input fields admission reads: the selected action and a named target session. */
|
|
73
|
+
const CallInputSchema = z.object({
|
|
74
|
+
action: z.string().min(1).optional().catch(undefined),
|
|
75
|
+
sessionId: z.uuid().optional().catch(undefined)
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Whether the call writes, by the platform's one rule (the same one host
|
|
79
|
+
* approval uses, external/src/harness/live-tools.ts): the selected action's
|
|
80
|
+
* declared safety, else the tool's; only a declared `read` is a read.
|
|
81
|
+
*/
|
|
82
|
+
export function callWrites(fields, input) {
|
|
83
|
+
const actionSafety = fields.schemas?.actionSafety;
|
|
84
|
+
const selected = input.action ? actionSafety?.[input.action] : undefined;
|
|
85
|
+
if (selected !== undefined)
|
|
86
|
+
return selected !== 'read';
|
|
87
|
+
if (!input.action && actionSafety && Object.values(actionSafety).some((safety) => safety !== 'read'))
|
|
88
|
+
return true;
|
|
89
|
+
return fields.safety !== 'read';
|
|
90
|
+
}
|
|
91
|
+
/** The tool whose own lifecycle binds and creates sessions; admission never mints for it. */
|
|
92
|
+
const SESSION_LIFECYCLE_TOOL = 'session';
|
|
93
|
+
/** The participant a caller acts as: declared, else its harness seat, else its agent identity. */
|
|
94
|
+
async function participantFor(manager, caller) {
|
|
95
|
+
if (caller?.participantId)
|
|
96
|
+
return caller.participantId;
|
|
97
|
+
if (caller?.agentId && caller.harnessSessionId) {
|
|
98
|
+
return (await manager.ensureHarnessSeat({ agentId: caller.agentId, harnessSessionId: caller.harnessSessionId })).participantId;
|
|
99
|
+
}
|
|
100
|
+
if (caller?.agentId)
|
|
101
|
+
return manager.identifyParticipant(caller.agentId);
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Admit one call. Its instance is registered and kept alive. Its session is,
|
|
106
|
+
* in order: the session the caller already carries; the session the call names
|
|
107
|
+
* (`input.sessionId`, e.g. a message into a room); the session its instance is
|
|
108
|
+
* working in. A call that writes and still has no session gets one, owned by
|
|
109
|
+
* its participant. Membership follows authorization: only once the call
|
|
110
|
+
* succeeds does the instance take the lease and work in that session; a
|
|
111
|
+
* failed write archives the session it minted.
|
|
112
|
+
*/
|
|
113
|
+
export async function admitCaller(manager, request, describeTool) {
|
|
114
|
+
const instance = instanceFor(request, manager.hostKey);
|
|
115
|
+
if (!instance)
|
|
116
|
+
return { caller: request.caller };
|
|
117
|
+
const registered = await manager.ensureInstance({
|
|
118
|
+
...instance,
|
|
119
|
+
clientName: instance.harness ?? instance.agentId ?? instance.transport
|
|
120
|
+
});
|
|
121
|
+
const input = CallInputSchema.parse(request.input ?? {});
|
|
122
|
+
// A session the call only names (a message into a room) makes the caller a
|
|
123
|
+
// member there; it does not become the session the instance works in.
|
|
124
|
+
const named = !request.caller?.sessionId && input.sessionId !== undefined;
|
|
125
|
+
let sessionId = request.caller?.sessionId ?? input.sessionId ?? (await manager.instanceSession(instance.instanceId));
|
|
126
|
+
let participantId = request.caller?.participantId;
|
|
127
|
+
let minted;
|
|
128
|
+
if (!sessionId && request.toolId !== SESSION_LIFECYCLE_TOOL && callWrites(describeTool(request.toolId), input)) {
|
|
129
|
+
participantId ??= await participantFor(manager, request.caller);
|
|
130
|
+
if (participantId) {
|
|
131
|
+
const created = await manager.createSession({
|
|
132
|
+
title: `${registered.handle ?? instance.instanceId} session`,
|
|
133
|
+
ownerParticipant: participantId,
|
|
134
|
+
status: 'active',
|
|
135
|
+
metadata: { source: 'write-admission', instanceId: instance.instanceId, transport: instance.transport }
|
|
136
|
+
});
|
|
137
|
+
minted = created.id;
|
|
138
|
+
sessionId = created.id;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const caller = {
|
|
142
|
+
...request.caller,
|
|
143
|
+
instanceId: instance.instanceId
|
|
144
|
+
};
|
|
145
|
+
if (sessionId)
|
|
146
|
+
caller.sessionId = sessionId;
|
|
147
|
+
if (participantId)
|
|
148
|
+
caller.participantId = participantId;
|
|
149
|
+
const settle = async (succeeded) => {
|
|
150
|
+
if (!succeeded) {
|
|
151
|
+
if (minted)
|
|
152
|
+
await manager.archiveSession(minted);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!sessionId || !participantId)
|
|
156
|
+
return;
|
|
157
|
+
await manager.ensureInstanceMembership({ instanceId: instance.instanceId, sessionId, participantId });
|
|
158
|
+
if (!named)
|
|
159
|
+
await manager.setInstanceSession(instance.instanceId, sessionId);
|
|
160
|
+
};
|
|
161
|
+
return { caller, settle };
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=admit-caller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admit-caller.js","sourceRoot":"","sources":["../../src/admission/admit-caller.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,7 +43,7 @@ export declare function executeSessionInit(input: SessionInitInput, context: Ses
|
|
|
43
43
|
source: string;
|
|
44
44
|
role: string;
|
|
45
45
|
}[] | undefined;
|
|
46
|
-
parentSessionId?: string | undefined;
|
|
46
|
+
parentSessionId?: string | null | undefined;
|
|
47
47
|
assignedParticipant?: string | undefined;
|
|
48
48
|
pausedAt?: Date | undefined;
|
|
49
49
|
archivedAt?: Date | undefined;
|
|
@@ -96,7 +96,7 @@ export declare function executeSessionStatus(_input: SessionStatusInput, context
|
|
|
96
96
|
source: string;
|
|
97
97
|
role: string;
|
|
98
98
|
}[] | undefined;
|
|
99
|
-
parentSessionId?: string | undefined;
|
|
99
|
+
parentSessionId?: string | null | undefined;
|
|
100
100
|
assignedParticipant?: string | undefined;
|
|
101
101
|
pausedAt?: Date | undefined;
|
|
102
102
|
archivedAt?: Date | undefined;
|
|
@@ -133,7 +133,7 @@ export declare function executeSessionStatus(_input: SessionStatusInput, context
|
|
|
133
133
|
source: string;
|
|
134
134
|
role: string;
|
|
135
135
|
}[] | undefined;
|
|
136
|
-
parentSessionId?: string | undefined;
|
|
136
|
+
parentSessionId?: string | null | undefined;
|
|
137
137
|
assignedParticipant?: string | undefined;
|
|
138
138
|
pausedAt?: Date | undefined;
|
|
139
139
|
archivedAt?: Date | undefined;
|
|
@@ -228,7 +228,7 @@ export declare function executeSessionResume(input: SessionResumeInput, context:
|
|
|
228
228
|
source: string;
|
|
229
229
|
role: string;
|
|
230
230
|
}[] | undefined;
|
|
231
|
-
parentSessionId?: string | undefined;
|
|
231
|
+
parentSessionId?: string | null | undefined;
|
|
232
232
|
assignedParticipant?: string | undefined;
|
|
233
233
|
pausedAt?: Date | undefined;
|
|
234
234
|
archivedAt?: Date | undefined;
|
|
@@ -40,7 +40,7 @@ export declare function executeSessionInit(input: SessionInitInput, context: Ses
|
|
|
40
40
|
source: string;
|
|
41
41
|
role: string;
|
|
42
42
|
}[] | undefined;
|
|
43
|
-
parentSessionId?: string | undefined;
|
|
43
|
+
parentSessionId?: string | null | undefined;
|
|
44
44
|
assignedParticipant?: string | undefined;
|
|
45
45
|
pausedAt?: Date | undefined;
|
|
46
46
|
archivedAt?: Date | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `session.message.arrived`: a message addressed to an instance this runtime
|
|
3
|
+
* hosts has arrived, whichever process wrote it. A host that keeps a seat open
|
|
4
|
+
* subscribes (`runtime.hooks('session').on('messageArrived', …)`) to deliver it
|
|
5
|
+
* into the seat instead of polling the room.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod/v4';
|
|
8
|
+
import { VibesRuntime } from '@vibesdotdev/kernel';
|
|
9
|
+
export declare const SESSION_MESSAGE_ARRIVED_NAMESPACE = "session";
|
|
10
|
+
export declare const SESSION_MESSAGE_ARRIVED_EVENT_NAME = "messageArrived";
|
|
11
|
+
export declare const SESSION_MESSAGE_ARRIVED_EVENT_ID = "session.message.arrived";
|
|
12
|
+
export declare const SessionMessageArrivedEventSchema: z.ZodObject<{
|
|
13
|
+
instanceId: z.ZodString;
|
|
14
|
+
sessionId: z.ZodString;
|
|
15
|
+
messageId: z.ZodString;
|
|
16
|
+
fromParticipant: z.ZodString;
|
|
17
|
+
fromSlug: z.ZodString;
|
|
18
|
+
toParticipant: z.ZodString;
|
|
19
|
+
messageType: z.ZodString;
|
|
20
|
+
content: z.ZodString;
|
|
21
|
+
createdAt: z.ZodString;
|
|
22
|
+
runtime: z.ZodInstanceOf<VibesRuntime>;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
export type SessionMessageArrivedEvent = z.infer<typeof SessionMessageArrivedEventSchema>;
|
|
25
|
+
export declare const sessionMessageArrivedEvent: {
|
|
26
|
+
kind: "runtime/event";
|
|
27
|
+
id: string;
|
|
28
|
+
source: string;
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
trigger: string;
|
|
32
|
+
};
|
|
33
|
+
export default sessionMessageArrivedEvent;
|
|
34
|
+
//# sourceMappingURL=session.message-arrived.event.descriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.message-arrived.event.descriptor.d.ts","sourceRoot":"","sources":["../../src/events/session.message-arrived.event.descriptor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAsB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE,eAAO,MAAM,iCAAiC,YAAY,CAAC;AAC3D,eAAO,MAAM,kCAAkC,mBAAmB,CAAC;AACnE,eAAO,MAAM,gCAAgC,4BAA4B,CAAC;AAE1E,eAAO,MAAM,gCAAgC;;;;;;;;;;;iBAc3C,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,eAAO,MAAM,0BAA0B;;;;;;;CAOrC,CAAC;AAEH,eAAe,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `session.message.arrived`: a message addressed to an instance this runtime
|
|
3
|
+
* hosts has arrived, whichever process wrote it. A host that keeps a seat open
|
|
4
|
+
* subscribes (`runtime.hooks('session').on('messageArrived', …)`) to deliver it
|
|
5
|
+
* into the seat instead of polling the room.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod/v4';
|
|
8
|
+
import { createRuntimeAsset, VibesRuntime } from '@vibesdotdev/kernel';
|
|
9
|
+
export const SESSION_MESSAGE_ARRIVED_NAMESPACE = 'session';
|
|
10
|
+
export const SESSION_MESSAGE_ARRIVED_EVENT_NAME = 'messageArrived';
|
|
11
|
+
export const SESSION_MESSAGE_ARRIVED_EVENT_ID = 'session.message.arrived';
|
|
12
|
+
export const SessionMessageArrivedEventSchema = z.object({
|
|
13
|
+
/** The hosted instance the message is for. */
|
|
14
|
+
instanceId: z.string(),
|
|
15
|
+
sessionId: z.string(),
|
|
16
|
+
messageId: z.string(),
|
|
17
|
+
fromParticipant: z.string(),
|
|
18
|
+
/** The sender's display slug, so a woken seat can attribute who said what. */
|
|
19
|
+
fromSlug: z.string(),
|
|
20
|
+
toParticipant: z.string(),
|
|
21
|
+
messageType: z.string(),
|
|
22
|
+
content: z.string(),
|
|
23
|
+
createdAt: z.string(),
|
|
24
|
+
/** The runtime hosting the instance, so subscribers act on the right one. */
|
|
25
|
+
runtime: z.instanceof(VibesRuntime)
|
|
26
|
+
});
|
|
27
|
+
export const sessionMessageArrivedEvent = createRuntimeAsset({
|
|
28
|
+
kind: 'runtime/event',
|
|
29
|
+
id: SESSION_MESSAGE_ARRIVED_EVENT_ID,
|
|
30
|
+
source: SESSION_MESSAGE_ARRIVED_NAMESPACE,
|
|
31
|
+
name: 'Session Message Arrived',
|
|
32
|
+
description: 'Emitted when a message addressed to an instance this runtime hosts arrives, whichever process wrote it.',
|
|
33
|
+
trigger: 'custom'
|
|
34
|
+
});
|
|
35
|
+
export default sessionMessageArrivedEvent;
|
|
36
|
+
//# sourceMappingURL=session.message-arrived.event.descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.message-arrived.event.descriptor.js","sourceRoot":"","sources":["../../src/events/session.message-arrived.event.descriptor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,CAAC,MAAM,iCAAiC,GAAG,SAAS,CAAC;AAC3D,MAAM,CAAC,MAAM,kCAAkC,GAAG,gBAAgB,CAAC;AACnE,MAAM,CAAC,MAAM,gCAAgC,GAAG,yBAAyB,CAAC;AAE1E,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACxD,8CAA8C;IAC9C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;IAC3B,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,6EAA6E;IAC7E,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC;CACnC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,0BAA0B,GAAG,kBAAkB,CAAC;IAC5D,IAAI,EAAE,eAAe;IACrB,EAAE,EAAE,gCAAgC;IACpC,MAAM,EAAE,iCAAiC;IACzC,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,yGAAyG;IACtH,OAAO,EAAE,QAAQ;CACjB,CAAC,CAAC;AAEH,eAAe,0BAA0B,CAAC"}
|
package/dist/manager.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { RuntimeInvokeCaller } from '@vibesdotdev/kernel/schemas/invoke-cal
|
|
|
16
16
|
import type { VibesLink } from '@vibesdotdev/shared/schemas';
|
|
17
17
|
import { type HarnessSeat, type HarnessSeatRegistration } from './schemas/harness-seat.ts';
|
|
18
18
|
import type { SessionMembershipLease } from './storage/session-membership-leases.record.descriptor.ts';
|
|
19
|
-
import type { Session, SessionCreate, SessionUpdate, SessionFilters, SessionSummary, Todo, TodoCreate, TodoUpdate, TodoFilters, TodoWithComputed, ScratchpadEntry, ScratchpadEntryCreate, ScratchpadEntryUpdate, ScratchpadFilters, ScratchpadSummary, JobRef, JobRefCreate, JobRefUpdate, JobFilters, JobSummary, ParticipantMessage, ParticipantMessageCreate, MessageFilters, ParticipantProfile, ParticipantProfileCreate, ParticipantProfileUpdate, ParticipantFilters, ParticipantConnection, KnowledgeRef, KnowledgeRefCreate, KnowledgeRefFilters, SessionPresence, SessionPresenceSummary } from './schemas/index.ts';
|
|
19
|
+
import type { Session, SessionCreate, SessionUpdate, SessionFilters, SessionSummary, Todo, TodoCreate, TodoUpdate, TodoFilters, TodoWithComputed, ScratchpadEntry, ScratchpadEntryCreate, ScratchpadEntryUpdate, ScratchpadFilters, ScratchpadSummary, JobRef, JobRefCreate, JobRefUpdate, JobFilters, JobSummary, ParticipantMessage, ParticipantMessageCreate, MessageFilters, ParticipantProfile, ParticipantProfileCreate, ParticipantProfileUpdate, ParticipantFilters, ParticipantConnection, RegisterInstanceInput, KnowledgeRef, KnowledgeRefCreate, KnowledgeRefFilters, SessionPresence, SessionPresenceSummary } from './schemas/index.ts';
|
|
20
20
|
/**
|
|
21
21
|
* Key-order-independent JSON so metadata comparison can't flake on insertion
|
|
22
22
|
* order: every object's keys are emitted sorted, arrays keep their order, and
|
|
@@ -154,6 +154,13 @@ export declare class SessionManager {
|
|
|
154
154
|
}): Promise<Session>;
|
|
155
155
|
getSession(id: string): Promise<Session | null>;
|
|
156
156
|
updateSession(id: string, updates: SessionUpdate): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* Place a session under a parent session (a subsession), or make it top
|
|
159
|
+
* level with `null`. The parent must exist, and may not be the session itself
|
|
160
|
+
* or any of its descendants: a cycle is refused `INVALID_INPUT
|
|
161
|
+
* session-parent-cycle`.
|
|
162
|
+
*/
|
|
163
|
+
setSessionParent(sessionId: string, parentSessionId: string | null): Promise<void>;
|
|
157
164
|
/**
|
|
158
165
|
* Bump a session's activity clock to reflect real traffic (messages), so
|
|
159
166
|
* `lastActivityAt` tracks when the session was last USED — not merely when its
|
|
@@ -395,6 +402,96 @@ export declare class SessionManager {
|
|
|
395
402
|
pruneOrphanedParticipantProfiles(): Promise<PruneOrphanedProfilesResult>;
|
|
396
403
|
recordConnection(connection: Omit<ParticipantConnection, 'connectedAt' | 'disconnectedAt'>): Promise<ParticipantConnection>;
|
|
397
404
|
closeConnection(connectionId: string): Promise<void>;
|
|
405
|
+
private static readonly INSTANCE_TTL_MS;
|
|
406
|
+
private static readonly INSTANCE_HEARTBEAT_MS;
|
|
407
|
+
/** Touches inside this window are not rewritten: one write per instance per window. */
|
|
408
|
+
private static readonly INSTANCE_TOUCH_MIN_MS;
|
|
409
|
+
private static readonly INSTANCE_HANDLE_ATTEMPTS;
|
|
410
|
+
/** This host's own key: distinguishes its in-process seats from another host's. */
|
|
411
|
+
readonly hostKey: string;
|
|
412
|
+
private readonly hostedInstances;
|
|
413
|
+
private readonly instanceTouchedAt;
|
|
414
|
+
/** Handles of instances this host registered, so a touch need not reread them. */
|
|
415
|
+
private readonly instanceHandles;
|
|
416
|
+
/** (instance, session, participant) triples this host has already leased. */
|
|
417
|
+
private readonly instanceMemberships;
|
|
418
|
+
private instanceHeartbeat?;
|
|
419
|
+
private static readonly INSTANCE_DELIVERY_MS;
|
|
420
|
+
/** Per hosted instance: messages newer than this have not been announced yet. */
|
|
421
|
+
private readonly deliveryCursors;
|
|
422
|
+
private instanceDelivery?;
|
|
423
|
+
private deliveryInFlight;
|
|
424
|
+
private static isLiveInstance;
|
|
425
|
+
private static randomHandle;
|
|
426
|
+
/**
|
|
427
|
+
* Register (or re-register) a running instance and give it a handle. A
|
|
428
|
+
* chosen handle held by another LIVE instance is refused `CONFLICT
|
|
429
|
+
* instance-handle-taken` naming the holder; one held by an expired or closed
|
|
430
|
+
* instance is reclaimed. With no choice the instance keeps its live handle,
|
|
431
|
+
* else gets a random `<agent>-<4>` handle. Uniqueness is the storage index
|
|
432
|
+
* on `activeHandle`, not this check: a lost race is retried (random) or
|
|
433
|
+
* refused (chosen).
|
|
434
|
+
*/
|
|
435
|
+
registerInstance(input: RegisterInstanceInput): Promise<ParticipantConnection>;
|
|
436
|
+
/** Free `handle` when its holder is no longer live, so a new instance can take it. */
|
|
437
|
+
private releaseExpiredHandle;
|
|
438
|
+
/** The live instance holding `handle`, if any. */
|
|
439
|
+
liveInstanceByHandle(handle: string): Promise<ParticipantConnection | null>;
|
|
440
|
+
/**
|
|
441
|
+
* Mark an instance alive now and renew the membership leases it holds.
|
|
442
|
+
* Writes at most once per touch window per instance.
|
|
443
|
+
*/
|
|
444
|
+
touchInstance(instanceId: string, options?: {
|
|
445
|
+
force?: boolean;
|
|
446
|
+
}): Promise<boolean>;
|
|
447
|
+
/**
|
|
448
|
+
* Keep an admitted caller's instance live: register it the first time this
|
|
449
|
+
* host sees it (or after it was closed), otherwise touch it.
|
|
450
|
+
*/
|
|
451
|
+
ensureInstance(input: RegisterInstanceInput): Promise<{
|
|
452
|
+
handle?: string;
|
|
453
|
+
}>;
|
|
454
|
+
/**
|
|
455
|
+
* Make an instance a member of the session it calls with: one lease keyed
|
|
456
|
+
* on the instance, taken the first time this host sees the pair and renewed
|
|
457
|
+
* by every touch after. An archived or missing session takes no member.
|
|
458
|
+
*/
|
|
459
|
+
ensureInstanceMembership(input: {
|
|
460
|
+
instanceId: string;
|
|
461
|
+
sessionId: string;
|
|
462
|
+
participantId: string;
|
|
463
|
+
}): Promise<void>;
|
|
464
|
+
/**
|
|
465
|
+
* Give a live instance the handle it chose. The registry's uniqueness rule
|
|
466
|
+
* applies: a handle another live instance holds is refused naming its holder.
|
|
467
|
+
*/
|
|
468
|
+
chooseInstanceHandle(instanceId: string, handle: string): Promise<ParticipantConnection>;
|
|
469
|
+
/** One instance's registry row. */
|
|
470
|
+
getInstance(instanceId: string): Promise<ParticipantConnection | null>;
|
|
471
|
+
/** Record the session an instance is working in (its bind, or its first write). */
|
|
472
|
+
setInstanceSession(instanceId: string, sessionId: string): Promise<void>;
|
|
473
|
+
/** The session an instance is working in, while that session is still open. */
|
|
474
|
+
instanceSession(instanceId: string): Promise<string | undefined>;
|
|
475
|
+
/** Close an instance: it stops being live, frees its handle and releases its leases. */
|
|
476
|
+
closeInstance(instanceId: string): Promise<void>;
|
|
477
|
+
/** Every live instance in this store: who is here, however they arrived. */
|
|
478
|
+
listLiveInstances(): Promise<ParticipantConnection[]>;
|
|
479
|
+
private forgetInstance;
|
|
480
|
+
private unreleasedLeasesOf;
|
|
481
|
+
/**
|
|
482
|
+
* Heartbeat hosted instances on this runtime's lifecycle interval, so the
|
|
483
|
+
* kernel stops it at disposal. A finite host (a one-shot command) runs no
|
|
484
|
+
* interval: its instance lives by activity and closes with the manager.
|
|
485
|
+
*/
|
|
486
|
+
private hostInstance;
|
|
487
|
+
private stopInstanceHeartbeat;
|
|
488
|
+
/**
|
|
489
|
+
* Announce, on this runtime's `session` hook bus, every message addressed to
|
|
490
|
+
* a hosted instance's participant that arrived since the last check, whichever
|
|
491
|
+
* process wrote it (`session.message.arrived`). Starts from the moment the
|
|
492
|
+
* instance was hosted, so history is never replayed as new.
|
|
493
|
+
*/
|
|
494
|
+
announceArrivedMessages(): Promise<number>;
|
|
398
495
|
getConnectionHistory(participantId?: string, limit?: number): Promise<ParticipantConnection[]>;
|
|
399
496
|
addKnowledgeRef(sessionId: string, ref: KnowledgeRefCreate): Promise<KnowledgeRef>;
|
|
400
497
|
getKnowledgeRef(id: string): Promise<KnowledgeRef | null>;
|
|
@@ -475,7 +572,7 @@ export declare class SessionManager {
|
|
|
475
572
|
source: string;
|
|
476
573
|
role: string;
|
|
477
574
|
}[] | undefined;
|
|
478
|
-
parentSessionId?: string | undefined;
|
|
575
|
+
parentSessionId?: string | null | undefined;
|
|
479
576
|
assignedParticipant?: string | undefined;
|
|
480
577
|
pausedAt?: Date | undefined;
|
|
481
578
|
archivedAt?: Date | undefined;
|