@akagilnc/pi-workflow-roles 0.1.3771 → 0.1.3789
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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +793 -393
- package/dist/atomic-write.js +23 -0
- package/dist/collector-handbook.js +142 -0
- package/dist/collector-ledger.js +39 -47
- package/dist/collector-role.js +103 -14
- package/dist/collector-tool-schemas.js +25 -1
- package/dist/headless-host/description.js +77 -0
- package/dist/headless-host/mcp-relay.mjs +119 -0
- package/dist/headless-host/production-host.js +26841 -0
- package/dist/host-descriptions.js +44 -3
- package/dist/public-cli/load-production-external-host.js +19 -0
- package/dist/public-cli/load-production-headless-host.js +36 -0
- package/dist/public-cli/main.js +244 -234
- package/dist/public-cli/option-definitions.js +2 -2
- package/dist/public-role-summons.js +40 -5
- package/dist/role-runtime.js +3 -0
- package/extensions/role-runtime.ts +2 -0
- package/package.json +1 -1
- package/resources/collector-bot-handbook.md +33 -0
- package/scripts/build-package.mjs +28 -0
- package/src/acp-host/production-host.ts +4 -0
- package/src/acp-host/role-envelope.ts +141 -84
- package/src/acp-host/role-turn-host.ts +12 -0
- package/src/collector-handbook.ts +194 -0
- package/src/collector-ledger.ts +42 -62
- package/src/collector-role.ts +117 -11
- package/src/collector-tool-schemas.ts +25 -1
- package/src/headless-host/description.ts +123 -0
- package/src/headless-host/production-host.ts +75 -0
- package/src/headless-host/role-turn-host.ts +424 -0
- package/src/host-descriptions.ts +53 -6
- package/src/public-cli/cli.ts +2 -2
- package/src/public-cli/load-production-external-host.ts +29 -0
- package/src/public-cli/load-production-headless-host.ts +48 -0
- package/src/public-cli/main.ts +5 -0
- package/src/public-cli/option-definitions.ts +2 -2
- package/src/public-role-summons.ts +62 -9
- package/src/role-runtime.ts +5 -0
package/src/host-descriptions.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Packaged host description
|
|
3
|
-
* Key = seat-table `host` value
|
|
2
|
+
* Packaged host description tables (#729 / #731 / #645).
|
|
3
|
+
* Key = seat-table `host` value.
|
|
4
|
+
* - ACP family rows feed the generic ACP factory.
|
|
5
|
+
* - Headless CLI family rows feed the generic headless factory (#645; #646 codex next).
|
|
4
6
|
* pi is the in-process default, not a row.
|
|
5
|
-
* Unregistered names fail closed (#510);
|
|
7
|
+
* Unregistered names fail closed (#510); these tables do not fallback.
|
|
6
8
|
*/
|
|
7
9
|
import type { AcpHostDescription } from "./acp-host/description.ts";
|
|
10
|
+
import type { HeadlessHostDescription } from "./headless-host/description.ts";
|
|
8
11
|
|
|
9
12
|
/** Grok CLI reads vendor-private compat surfaces unless each is disabled by name. */
|
|
10
13
|
const PRIVATE_COMPAT_ENV = Object.fromEntries(
|
|
@@ -15,6 +18,8 @@ const PRIVATE_COMPAT_ENV = Object.fromEntries(
|
|
|
15
18
|
|
|
16
19
|
export const DEFAULT_ROLE_TURN_HOST = "pi" as const;
|
|
17
20
|
|
|
21
|
+
export type HostFamily = "acp" | "headless";
|
|
22
|
+
|
|
18
23
|
export const HOST_DESCRIPTIONS: Readonly<Record<string, AcpHostDescription>> = Object.freeze({
|
|
19
24
|
/** Operator home `~/.grok`, native session/load resume, `agent [--model X] stdio`. */
|
|
20
25
|
"grok-build": Object.freeze({
|
|
@@ -60,17 +65,59 @@ export const HOST_DESCRIPTIONS: Readonly<Record<string, AcpHostDescription>> = O
|
|
|
60
65
|
}),
|
|
61
66
|
});
|
|
62
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Headless CLI family (#645). Claude is the first row; codex (#646) adds another.
|
|
70
|
+
* fixedArgs: print mode, isolation without `--bare` (OAuth stays), full permissions.
|
|
71
|
+
* `--setting-sources` empty = load no user/project/local CLAUDE.md/hooks/skills
|
|
72
|
+
* (role envelope is delivered via `--system-prompt` wholesale replace).
|
|
73
|
+
* `--strict-mcp-config` with no `--mcp-config` drops operator MCP + claude.ai connectors.
|
|
74
|
+
*/
|
|
75
|
+
export const HEADLESS_HOST_DESCRIPTIONS: Readonly<Record<string, HeadlessHostDescription>> = Object.freeze({
|
|
76
|
+
"claude": Object.freeze({
|
|
77
|
+
binaryFromHome: Object.freeze([".local", "bin", "claude"]),
|
|
78
|
+
sessionBindingFile: "claude-headless-session.json",
|
|
79
|
+
fixedArgs: Object.freeze([
|
|
80
|
+
// One result envelope (not stream-json): typed receipt only; no event-stream copy.
|
|
81
|
+
"--output-format", "json",
|
|
82
|
+
"--permission-mode", "bypassPermissions",
|
|
83
|
+
// Empty sources: no user/project/local operator surface (envelope owns materials).
|
|
84
|
+
"--setting-sources", "",
|
|
85
|
+
// With adapter-supplied --mcp-config only (AK relay); drops operator + claude.ai MCP.
|
|
86
|
+
"--strict-mcp-config",
|
|
87
|
+
]),
|
|
88
|
+
promptFlag: "-p",
|
|
89
|
+
modelFlag: "--model",
|
|
90
|
+
effortFlag: "--effort",
|
|
91
|
+
// File path keeps large role envelopes off ARG_MAX.
|
|
92
|
+
systemPromptFlag: "--system-prompt-file",
|
|
93
|
+
jsonSchemaFlag: "--json-schema",
|
|
94
|
+
mcpConfigFlag: "--mcp-config",
|
|
95
|
+
sessionIdFlag: "--session-id",
|
|
96
|
+
resumeFlag: "--resume",
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
|
|
63
100
|
export function lookupHostDescription(host: string): AcpHostDescription | undefined {
|
|
64
101
|
return Object.hasOwn(HOST_DESCRIPTIONS, host) ? HOST_DESCRIPTIONS[host] : undefined;
|
|
65
102
|
}
|
|
66
103
|
|
|
104
|
+
export function lookupHeadlessHostDescription(host: string): HeadlessHostDescription | undefined {
|
|
105
|
+
return Object.hasOwn(HEADLESS_HOST_DESCRIPTIONS, host) ? HEADLESS_HOST_DESCRIPTIONS[host] : undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function lookupHostFamily(host: string): HostFamily | undefined {
|
|
109
|
+
if (lookupHostDescription(host) !== undefined) return "acp";
|
|
110
|
+
if (lookupHeadlessHostDescription(host) !== undefined) return "headless";
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
67
114
|
export function packagedExternalHostNames(): readonly string[] {
|
|
68
|
-
return Object.keys(HOST_DESCRIPTIONS);
|
|
115
|
+
return [...Object.keys(HOST_DESCRIPTIONS), ...Object.keys(HEADLESS_HOST_DESCRIPTIONS)];
|
|
69
116
|
}
|
|
70
117
|
|
|
71
|
-
/** Legal persistent/invocation host: default pi, or a table key. */
|
|
118
|
+
/** Legal persistent/invocation host: default pi, or a table key (any family). */
|
|
72
119
|
export function assertRegisteredHostName(host: string): string {
|
|
73
|
-
if (host === DEFAULT_ROLE_TURN_HOST ||
|
|
120
|
+
if (host === DEFAULT_ROLE_TURN_HOST || lookupHostFamily(host) !== undefined) {
|
|
74
121
|
return host;
|
|
75
122
|
}
|
|
76
123
|
throw new Error(`unregistered host: ${host}`);
|
package/src/public-cli/cli.ts
CHANGED
|
@@ -45,7 +45,7 @@ import type { CliIo } from "./cli-io.ts";
|
|
|
45
45
|
import type { PostAdmissionEnv } from "./post-admission.ts";
|
|
46
46
|
import type { RoleTurnHost, RoleTurnRequest } from "../host-contracts.ts";
|
|
47
47
|
import { packagedExternalHostNames } from "../host-descriptions.ts";
|
|
48
|
-
import {
|
|
48
|
+
import { loadProductionExternalHostFactory } from "./load-production-external-host.ts";
|
|
49
49
|
import {
|
|
50
50
|
createPiRoleTurnHost,
|
|
51
51
|
appendPiSessionCustomEntry,
|
|
@@ -347,7 +347,7 @@ function resolveRoleTurnHost(
|
|
|
347
347
|
ok: true as const,
|
|
348
348
|
host: {
|
|
349
349
|
executeTurn: async (request: RoleTurnRequest) => {
|
|
350
|
-
hostPromise ??=
|
|
350
|
+
hostPromise ??= loadProductionExternalHostFactory(env.packageRoot, name).then((create) =>
|
|
351
351
|
create({
|
|
352
352
|
packageRoot: env.packageRoot,
|
|
353
353
|
principalAuthority: options.principalAuthority,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Family-dispatch loader for packaged external RoleTurnHost factories (#645).
|
|
3
|
+
* ACP rows → production ACP host; headless rows → production headless host.
|
|
4
|
+
* Unregistered names fail closed before any import.
|
|
5
|
+
*/
|
|
6
|
+
import { lookupHostFamily } from "../host-descriptions.ts";
|
|
7
|
+
import type { DurablePrincipalAuthority, RoleTurnHost } from "../host-contracts.ts";
|
|
8
|
+
import { loadProductionAcpHostFactory } from "./load-production-acp-host.ts";
|
|
9
|
+
import { loadProductionHeadlessHostFactory } from "./load-production-headless-host.ts";
|
|
10
|
+
|
|
11
|
+
export type ProductionExternalHostFactory = (options: {
|
|
12
|
+
packageRoot: string;
|
|
13
|
+
principalAuthority: DurablePrincipalAuthority;
|
|
14
|
+
}) => RoleTurnHost;
|
|
15
|
+
|
|
16
|
+
/** Resolve the production host factory for one registered external host key. */
|
|
17
|
+
export async function loadProductionExternalHostFactory(
|
|
18
|
+
packageRoot: string,
|
|
19
|
+
host: string,
|
|
20
|
+
): Promise<ProductionExternalHostFactory> {
|
|
21
|
+
const family = lookupHostFamily(host);
|
|
22
|
+
if (family === "acp") {
|
|
23
|
+
return loadProductionAcpHostFactory(packageRoot, host);
|
|
24
|
+
}
|
|
25
|
+
if (family === "headless") {
|
|
26
|
+
return loadProductionHeadlessHostFactory(packageRoot, host);
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`unregistered host: ${host}`);
|
|
29
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deferred loader for the packaged generic headless RoleTurnHost factory (#645).
|
|
3
|
+
*
|
|
4
|
+
* Public ak-role bin must not statically value-import the production host (or its
|
|
5
|
+
* role-runtime edges). Specifier is runtime-constructed so esbuild leaves this
|
|
6
|
+
* import external (ADR 0052 discovery stays peer-free).
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { pathToFileURL } from "node:url";
|
|
11
|
+
|
|
12
|
+
import type { HeadlessHostDescription } from "../headless-host/description.ts";
|
|
13
|
+
import { lookupHeadlessHostDescription } from "../host-descriptions.ts";
|
|
14
|
+
import type { DurablePrincipalAuthority, RoleTurnHost } from "../host-contracts.ts";
|
|
15
|
+
|
|
16
|
+
export type ProductionHeadlessHostFactory = (options: {
|
|
17
|
+
packageRoot: string;
|
|
18
|
+
principalAuthority: DurablePrincipalAuthority;
|
|
19
|
+
}) => RoleTurnHost;
|
|
20
|
+
|
|
21
|
+
type GenericHeadlessHostFactory = (options: {
|
|
22
|
+
packageRoot: string;
|
|
23
|
+
principalAuthority: DurablePrincipalAuthority;
|
|
24
|
+
description: HeadlessHostDescription;
|
|
25
|
+
}) => RoleTurnHost;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the production headless host factory for one registered headless host
|
|
29
|
+
* key without a static graph edge into the public CLI bundle.
|
|
30
|
+
*/
|
|
31
|
+
export async function loadProductionHeadlessHostFactory(
|
|
32
|
+
packageRoot: string,
|
|
33
|
+
host: string,
|
|
34
|
+
): Promise<ProductionHeadlessHostFactory> {
|
|
35
|
+
const description = lookupHeadlessHostDescription(host);
|
|
36
|
+
if (description === undefined) {
|
|
37
|
+
throw new Error(`unregistered headless host: ${host}`);
|
|
38
|
+
}
|
|
39
|
+
const built = join(packageRoot, "dist/headless-host/production-host.js");
|
|
40
|
+
const source = join(packageRoot, "src/headless-host/production-host.ts");
|
|
41
|
+
const target = existsSync(built) ? built : source;
|
|
42
|
+
const href = pathToFileURL(target).href;
|
|
43
|
+
const mod = (await import(href)) as {
|
|
44
|
+
createProductionHeadlessRoleTurnHost: GenericHeadlessHostFactory;
|
|
45
|
+
};
|
|
46
|
+
const create = mod.createProductionHeadlessRoleTurnHost;
|
|
47
|
+
return (options) => create({ ...options, description });
|
|
48
|
+
}
|
package/src/public-cli/main.ts
CHANGED
|
@@ -26,6 +26,11 @@ function resolvePackageRoot(binDir: string): string {
|
|
|
26
26
|
|
|
27
27
|
const packageRoot = resolvePackageRoot(here);
|
|
28
28
|
|
|
29
|
+
// Nested institutional summons resolve package root from this env (#675 / #645).
|
|
30
|
+
// Pin to the running bin's package so a stale outer install pin cannot load a
|
|
31
|
+
// host family this tree owns but the older install lacks.
|
|
32
|
+
process.env.AK_ROLE_PACKAGE_ROOT = packageRoot;
|
|
33
|
+
|
|
29
34
|
// The host-provided runtime must be resolvable before the CLI module graph loads it.
|
|
30
35
|
ensureHostPiRuntimeResolvable(packageRoot);
|
|
31
36
|
|
|
@@ -598,8 +598,8 @@ const COLLECTOR_OPTIONS = [
|
|
|
598
598
|
repeatable: false,
|
|
599
599
|
form: "option",
|
|
600
600
|
description: {
|
|
601
|
-
en: "Optional request manifest JSON path ({requests:[{id,body}]}).",
|
|
602
|
-
zh: "可选 request manifest JSON 路径({requests:[{id,body}]}
|
|
601
|
+
en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
|
|
602
|
+
zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。角色亦可依手册/现场自行判定请求正文,不必依赖本文件。",
|
|
603
603
|
},
|
|
604
604
|
},
|
|
605
605
|
] as const satisfies readonly PublicOptionDefinition[];
|
|
@@ -65,6 +65,12 @@ export type PublicSummonRequest = {
|
|
|
65
65
|
* Never folded into argv / parent-run lookup keys (ADR 0079 卷宗指针 stays pure).
|
|
66
66
|
*/
|
|
67
67
|
readonly gateReviewInstruction?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Parent-invocation host axis (#617 / #645). Nested institutional legs inherit
|
|
70
|
+
* the live parent `--host` so a single public entry does not require mutating
|
|
71
|
+
* persistent seat host. Seat model/thinking stay on the officer seat table.
|
|
72
|
+
*/
|
|
73
|
+
readonly host?: string;
|
|
68
74
|
/**
|
|
69
75
|
* Offline test inject — same face as public CLI env.roleTurnHost. Production
|
|
70
76
|
* summons leave this unset and use the seat-resolved host.
|
|
@@ -211,14 +217,13 @@ async function createSummonEnv(options: {
|
|
|
211
217
|
const hostName = options.seat.host ?? "pi";
|
|
212
218
|
let roleTurnHost = piHost;
|
|
213
219
|
if (hostName !== "pi") {
|
|
214
|
-
const {
|
|
215
|
-
const {
|
|
216
|
-
"./public-cli/load-production-
|
|
220
|
+
const { lookupHostFamily } = await import("./host-descriptions.ts");
|
|
221
|
+
const { loadProductionExternalHostFactory } = await import(
|
|
222
|
+
"./public-cli/load-production-external-host.ts"
|
|
217
223
|
);
|
|
218
|
-
// #729:
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
if (lookupHostDescription(hostName) === undefined) {
|
|
224
|
+
// #729 / #645: description tables are the sole host authority — family
|
|
225
|
+
// dispatch (ACP vs headless) is data-driven. Unregistered keys fail closed.
|
|
226
|
+
if (lookupHostFamily(hostName) === undefined) {
|
|
222
227
|
throw new Error(
|
|
223
228
|
`public role summons host unregistered: host=${hostName} seat=${options.role}`,
|
|
224
229
|
);
|
|
@@ -226,7 +231,7 @@ async function createSummonEnv(options: {
|
|
|
226
231
|
let hostPromise: Promise<RoleTurnHost> | undefined;
|
|
227
232
|
roleTurnHost = {
|
|
228
233
|
executeTurn: async (request) => {
|
|
229
|
-
hostPromise ??=
|
|
234
|
+
hostPromise ??= loadProductionExternalHostFactory(options.packageRoot, hostName).then(
|
|
230
235
|
(create) =>
|
|
231
236
|
create({
|
|
232
237
|
packageRoot: options.packageRoot,
|
|
@@ -286,7 +291,10 @@ export async function summonPublicRole(
|
|
|
286
291
|
const credentials =
|
|
287
292
|
options.credentials ?? (await loadCredentialProviders(agentDir));
|
|
288
293
|
const config = await loadPublicCliConfig(home);
|
|
289
|
-
|
|
294
|
+
// Nested legs inherit parent invocation host when provided (#645 review path).
|
|
295
|
+
// Model/thinking stay on the officer seat — host-only inherit (seat-table law).
|
|
296
|
+
const invocation = options.host === undefined ? undefined : { host: options.host };
|
|
297
|
+
const seat = resolveEffectiveSeat(config, options.role, credentials, invocation);
|
|
290
298
|
const env = {
|
|
291
299
|
...(await createSummonEnv({
|
|
292
300
|
role: options.role,
|
|
@@ -412,6 +420,47 @@ export async function summonPublicRole(
|
|
|
412
420
|
}
|
|
413
421
|
|
|
414
422
|
/** Gate officer summons: notary/auditor via --source-run; inspector via pointer instruction. */
|
|
423
|
+
/**
|
|
424
|
+
* Read parent invocation host so nested officers inherit live --host only (#645).
|
|
425
|
+
* Gate source runs necessarily own invocation.json — missing page, bad JSON, or
|
|
426
|
+
* bad shape stay loud (failure-honesty). Absent host field is lawful (seat default).
|
|
427
|
+
*/
|
|
428
|
+
async function parentInvocationHost(sourceRunDirectory: string): Promise<string | undefined> {
|
|
429
|
+
const { readFile } = await import("node:fs/promises");
|
|
430
|
+
const path = join(sourceRunDirectory, "invocation.json");
|
|
431
|
+
let text: string;
|
|
432
|
+
try {
|
|
433
|
+
text = await readFile(path, "utf8");
|
|
434
|
+
} catch (error) {
|
|
435
|
+
const code =
|
|
436
|
+
error instanceof Error && "code" in error
|
|
437
|
+
? (error as NodeJS.ErrnoException).code
|
|
438
|
+
: undefined;
|
|
439
|
+
throw new Error(
|
|
440
|
+
`parent invocation.json required for gate source run at ${path}: ${code ?? (error instanceof Error ? error.message : String(error))}`,
|
|
441
|
+
{ cause: error },
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
let raw: unknown;
|
|
445
|
+
try {
|
|
446
|
+
raw = JSON.parse(text) as unknown;
|
|
447
|
+
} catch (error) {
|
|
448
|
+
throw new Error(
|
|
449
|
+
`parent invocation.json unreadable at ${path}: ${error instanceof Error ? error.message : String(error)}`,
|
|
450
|
+
{ cause: error },
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
454
|
+
throw new Error(`parent invocation.json has non-object shape at ${path}`);
|
|
455
|
+
}
|
|
456
|
+
const host = (raw as Record<string, unknown>).host;
|
|
457
|
+
if (host === undefined) return undefined;
|
|
458
|
+
if (typeof host !== "string" || host.trim() === "") {
|
|
459
|
+
throw new Error(`parent invocation.json host must be a non-empty string at ${path}`);
|
|
460
|
+
}
|
|
461
|
+
return host;
|
|
462
|
+
}
|
|
463
|
+
|
|
415
464
|
export async function summonGateOfficer(options: {
|
|
416
465
|
readonly officer: "inspector" | "notary" | "auditor";
|
|
417
466
|
readonly sourceRunDirectory: string;
|
|
@@ -452,6 +501,9 @@ export async function summonGateOfficer(options: {
|
|
|
452
501
|
submission: options.submission,
|
|
453
502
|
});
|
|
454
503
|
}
|
|
504
|
+
// Inherit parent live --host only so review roundtrip stays on one host without
|
|
505
|
+
// mutating persistent seat tables (#645). Officer model/thinking stay seat-owned.
|
|
506
|
+
const parentHost = await parentInvocationHost(options.sourceRunDirectory);
|
|
455
507
|
const common = {
|
|
456
508
|
cwd: options.cwd,
|
|
457
509
|
...(home === undefined ? {} : { home }),
|
|
@@ -462,6 +514,7 @@ export async function summonGateOfficer(options: {
|
|
|
462
514
|
...(gateReviewInstruction === undefined
|
|
463
515
|
? {}
|
|
464
516
|
: { gateReviewInstruction }),
|
|
517
|
+
...(parentHost === undefined ? {} : { host: parentHost }),
|
|
465
518
|
...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
|
|
466
519
|
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
467
520
|
} as const;
|
package/src/role-runtime.ts
CHANGED
|
@@ -611,6 +611,8 @@ export type RoleRuntimeDependencies = {
|
|
|
611
611
|
/** Shared-seam issue-fetch capability for Reviewer Spec self-fetch (#343). */
|
|
612
612
|
createReviewerIssueFetcher?(): ReviewerIssueFetcher;
|
|
613
613
|
loadCollectorSoul?(): Promise<string>;
|
|
614
|
+
/** #677: optional packaged seed for first-use general bot handbook. */
|
|
615
|
+
loadCollectorHandbookSeed?(): Promise<string>;
|
|
614
616
|
createCollectorTransport?(): CollectorGitHubTransport;
|
|
615
617
|
loadDoctorSoul?(): Promise<string>;
|
|
616
618
|
loadNotarySoul?(): Promise<string>;
|
|
@@ -1717,6 +1719,9 @@ export function createRoleRuntimeExtension(
|
|
|
1717
1719
|
...(dependencies.createCollectorClock === undefined
|
|
1718
1720
|
? {}
|
|
1719
1721
|
: { createClock: dependencies.createCollectorClock }),
|
|
1722
|
+
...(dependencies.loadCollectorHandbookSeed === undefined
|
|
1723
|
+
? {}
|
|
1724
|
+
: { loadHandbookSeed: dependencies.loadCollectorHandbookSeed }),
|
|
1720
1725
|
},
|
|
1721
1726
|
hostActions,
|
|
1722
1727
|
);
|