@botlearn-course/daemon 0.0.13-beta.1 → 0.0.14
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 +5 -2
- package/dist/agent-service-sandbox.d.ts +5 -0
- package/dist/agent-service-sandbox.js +81 -19
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/course-skills-relay.d.ts +2 -0
- package/dist/mcp/course-skills-relay.js +54 -0
- package/dist/mcp/course-skills-server.d.ts +49 -0
- package/dist/mcp/course-skills-server.js +439 -0
- package/dist/run-dispatcher.d.ts +3 -0
- package/dist/run-dispatcher.js +64 -2
- package/dist/runtime-capabilities.d.ts +1 -0
- package/dist/runtime-capabilities.js +4 -0
- package/dist/runtime-env.js +2 -0
- package/dist/runtime-skills.d.ts +93 -0
- package/dist/runtime-skills.js +401 -0
- package/dist/runtimes/deepseek-tui.d.ts +11 -3
- package/dist/runtimes/deepseek-tui.js +488 -48
- package/dist/runtimes/engine.d.ts +10 -0
- package/dist/runtimes/engine.js +12 -5
- package/dist/runtimes/progress.d.ts +2 -0
- package/dist/runtimes/progress.js +34 -0
- package/dist/tool-observation.d.ts +21 -0
- package/dist/tool-observation.js +120 -0
- package/dist/types.d.ts +28 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,8 +114,11 @@ runtime 凭据。
|
|
|
114
114
|
- 本包 production 依赖为零,发布 tarball 只包含 `dist/`、`README.md`、`package.json`、
|
|
115
115
|
`LICENSE`(CI 发布前强制校验)。
|
|
116
116
|
- 托管 session 的 control token/reconnect state 位于 runtime UID 不可访问的 `0700` control home;
|
|
117
|
-
runtime workspace
|
|
118
|
-
|
|
117
|
+
runtime workspace 独立可写。activation-scoped Skill Provider binding 只留在 daemon control
|
|
118
|
+
process 内存;DeepSeek 只通过 clean-env `course_skills` Unix Socket relay 按需读取当前授权
|
|
119
|
+
`SKILL.md`/reference,endpoint/token 不进入 runtime env、MCP config、state、workspace 或日志。
|
|
120
|
+
Prompt Pack 仍通过受信 system context 应用。长期模型 provider key 留在 Agent Service,runtime
|
|
121
|
+
只拿 generation-scoped proxy grant。
|
|
119
122
|
|
|
120
123
|
## 发布
|
|
121
124
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Logger } from "./log.js";
|
|
2
|
+
import { type RuntimeSkillProviderFactory } from "./runtime-skills.js";
|
|
2
3
|
import { type PersistentSessionExecution, type PreparedPersistentTurn, type RunReportingClient } from "./run-dispatcher.js";
|
|
3
4
|
import type { CourseRuntime, CourseRuntimeProfile, RunEvent, RunFileCandidate, RunFileRecord, RunStartPayload } from "./types.js";
|
|
4
5
|
export interface AgentServiceSandboxOptions {
|
|
@@ -7,9 +8,12 @@ export interface AgentServiceSandboxOptions {
|
|
|
7
8
|
sandboxToken: string;
|
|
8
9
|
runtimes: Map<string, CourseRuntime>;
|
|
9
10
|
daemonVersion: string;
|
|
11
|
+
deepseekTuiVersion?: string;
|
|
10
12
|
log?: Logger;
|
|
11
13
|
random?: () => number;
|
|
12
14
|
sleep?: (ms: number) => Promise<void>;
|
|
15
|
+
/** Test/provider injection; production uses the bounded HTTP Runtime Skill Provider. */
|
|
16
|
+
prepareSkillProvider?: RuntimeSkillProviderFactory;
|
|
13
17
|
}
|
|
14
18
|
/**
|
|
15
19
|
* Long-running daemon client for one user-scoped managed sandbox (ADR-015).
|
|
@@ -23,6 +27,7 @@ export declare class AgentServiceSandboxClient implements RunReportingClient, Pe
|
|
|
23
27
|
private readonly log;
|
|
24
28
|
private readonly random;
|
|
25
29
|
private readonly sleep;
|
|
30
|
+
private readonly prepareSkillProvider;
|
|
26
31
|
private readonly state;
|
|
27
32
|
private readonly dispatcher;
|
|
28
33
|
/** agent_run_id → TURN scope(session/attempt/activation),事件与文件帧路由用。 */
|
|
@@ -3,9 +3,10 @@ import path from "node:path";
|
|
|
3
3
|
import { ensureDaemonHome } from "./auth-store.js";
|
|
4
4
|
import { AGENT_SERVICE_WS_SCHEMA, AGENT_SERVICE_WS_SUBPROTOCOL, createSandboxFrame, parseSandboxFrame, UnsupportedSandboxProtocolError, } from "./agent-service-ws-protocol.js";
|
|
5
5
|
import { log as defaultLog } from "./log.js";
|
|
6
|
-
import { availableRunCapabilities } from "./runtime-capabilities.js";
|
|
6
|
+
import { availableRunCapabilities, runtimeSupportsCourseSkills, } from "./runtime-capabilities.js";
|
|
7
7
|
import { activationRuntimeEnv, runtimeChildEnv } from "./runtime-env.js";
|
|
8
8
|
import { redactSecretString } from "./redaction.js";
|
|
9
|
+
import { parseRuntimeSkillProviderGrantSet, prepareRuntimeSkillProvider, RuntimeSkillProviderError, } from "./runtime-skills.js";
|
|
9
10
|
import { RunDispatcher, } from "./run-dispatcher.js";
|
|
10
11
|
import { ensureRuntimeSessionDirectories, ensureRuntimeSessionWorkspace, exposeRuntimeSessionWorkspace, removeRuntimeSessionWorkspace, revokeRuntimeSessionWorkspace, } from "./workspace.js";
|
|
11
12
|
import { WebSocketClient, } from "./websocket-client.js";
|
|
@@ -44,6 +45,9 @@ function inputAttachmentGrant(value) {
|
|
|
44
45
|
}
|
|
45
46
|
return { baseUrl: parsed.toString().replace(/\/$/, ""), token };
|
|
46
47
|
}
|
|
48
|
+
function runtimeSkillGrantKey(grants) {
|
|
49
|
+
return JSON.stringify(grants);
|
|
50
|
+
}
|
|
47
51
|
class SandboxClosedError extends Error {
|
|
48
52
|
code;
|
|
49
53
|
reason;
|
|
@@ -244,6 +248,7 @@ export class AgentServiceSandboxClient {
|
|
|
244
248
|
log;
|
|
245
249
|
random;
|
|
246
250
|
sleep;
|
|
251
|
+
prepareSkillProvider;
|
|
247
252
|
state;
|
|
248
253
|
dispatcher;
|
|
249
254
|
/** agent_run_id → TURN scope(session/attempt/activation),事件与文件帧路由用。 */
|
|
@@ -277,6 +282,8 @@ export class AgentServiceSandboxClient {
|
|
|
277
282
|
this.log = options.log ?? defaultLog;
|
|
278
283
|
this.random = options.random ?? Math.random;
|
|
279
284
|
this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
285
|
+
this.prepareSkillProvider =
|
|
286
|
+
options.prepareSkillProvider ?? ((raw) => prepareRuntimeSkillProvider(raw));
|
|
280
287
|
this.state = loadState(options.sandboxId, options.sandboxToken);
|
|
281
288
|
this.dispatcher = new RunDispatcher(this, options.runtimes, {
|
|
282
289
|
persistentSession: this,
|
|
@@ -313,10 +320,12 @@ export class AgentServiceSandboxClient {
|
|
|
313
320
|
return {
|
|
314
321
|
workspaceDir: prepared.workspaceDir,
|
|
315
322
|
transcriptFile: prepared.transcriptFile,
|
|
323
|
+
runtimeStateDir: prepared.rootDir,
|
|
316
324
|
nativeSessionId: session.nativeSessionId,
|
|
317
325
|
contextRevision,
|
|
318
326
|
runtimeEnv,
|
|
319
327
|
inputAttachmentGrant: activation.inputAttachmentGrant,
|
|
328
|
+
...(activation.skillProvider ? { skillProvider: activation.skillProvider } : {}),
|
|
320
329
|
};
|
|
321
330
|
}
|
|
322
331
|
persistNativeSession(nativeSessionId) {
|
|
@@ -678,6 +687,12 @@ export class AgentServiceSandboxClient {
|
|
|
678
687
|
await this.sendControlFrame("sandbox.ready", {
|
|
679
688
|
protocol_versions: [AGENT_SERVICE_WS_SCHEMA],
|
|
680
689
|
daemon_version: this.options.daemonVersion,
|
|
690
|
+
runtime_versions: {
|
|
691
|
+
course_daemon: this.options.daemonVersion,
|
|
692
|
+
...(this.options.deepseekTuiVersion
|
|
693
|
+
? { deepseek_tui: this.options.deepseekTuiVersion }
|
|
694
|
+
: {}),
|
|
695
|
+
},
|
|
681
696
|
resumed_sessions: Object.keys(this.state.sessions),
|
|
682
697
|
spool_frames: this.spoolFrameCount(),
|
|
683
698
|
});
|
|
@@ -842,33 +857,59 @@ export class AgentServiceSandboxClient {
|
|
|
842
857
|
await this.sendCommandAck(frame, "rejected", error instanceof Error ? error.message : "invalid_instructions");
|
|
843
858
|
return;
|
|
844
859
|
}
|
|
860
|
+
const rawSkillProvider = frame.payload.skill_provider;
|
|
861
|
+
const hasSkillProvider = rawSkillProvider !== undefined && rawSkillProvider !== null;
|
|
862
|
+
if (hasSkillProvider && !runtimeSupportsCourseSkills(runtimeId)) {
|
|
863
|
+
await this.sendCommandAck(frame, "rejected", "skill_provider_runtime_unsupported");
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
let skillGrantKey;
|
|
867
|
+
if (hasSkillProvider) {
|
|
868
|
+
try {
|
|
869
|
+
skillGrantKey = runtimeSkillGrantKey(parseRuntimeSkillProviderGrantSet(rawSkillProvider));
|
|
870
|
+
}
|
|
871
|
+
catch (error) {
|
|
872
|
+
const code = error instanceof RuntimeSkillProviderError
|
|
873
|
+
? error.code
|
|
874
|
+
: "skill_provider_binding_invalid";
|
|
875
|
+
await this.sendCommandAck(frame, "rejected", code);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
845
879
|
const capabilities = Array.isArray(frame.payload.capabilities)
|
|
846
880
|
? frame.payload.capabilities.filter((item) => typeof item === "string" && item.length > 0)
|
|
847
881
|
: [];
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
882
|
+
let availableCapabilities;
|
|
883
|
+
const missingCapabilities = (required) => {
|
|
884
|
+
if (required.length === 0)
|
|
885
|
+
return [];
|
|
886
|
+
if (!availableCapabilities) {
|
|
887
|
+
const workspace = ensureRuntimeSessionDirectories(sessionId, this.sandboxGeneration);
|
|
888
|
+
availableCapabilities = new Set(availableRunCapabilities({
|
|
889
|
+
agent_run_id: "activation-probe",
|
|
890
|
+
course_run_id: session.courseRunId ?? "",
|
|
891
|
+
lesson_id: null,
|
|
892
|
+
task_id: null,
|
|
893
|
+
agent_instance_id: null,
|
|
894
|
+
runtime: { id: runtimeId },
|
|
895
|
+
input: {},
|
|
896
|
+
context: {},
|
|
897
|
+
limits: {},
|
|
898
|
+
}, workspace.workspaceDir));
|
|
865
899
|
}
|
|
900
|
+
return Array.from(new Set(required.filter((item) => !availableCapabilities.has(item)))).sort();
|
|
901
|
+
};
|
|
902
|
+
const missingDeclaredCapabilities = missingCapabilities(capabilities);
|
|
903
|
+
if (missingDeclaredCapabilities.length > 0) {
|
|
904
|
+
await this.sendCommandAck(frame, "rejected", `missing_capabilities:${missingDeclaredCapabilities.join(",")}`);
|
|
905
|
+
return;
|
|
866
906
|
}
|
|
867
907
|
const existingActivation = this.activationContexts.get(sessionId);
|
|
868
908
|
if (existingActivation?.activationId === activationId) {
|
|
869
909
|
if (this.activeSessionId !== sessionId ||
|
|
870
910
|
session.runtimeId !== runtimeId ||
|
|
871
|
-
session.contextRevision !== contextRevision
|
|
911
|
+
session.contextRevision !== contextRevision ||
|
|
912
|
+
existingActivation.skillGrantKey !== skillGrantKey) {
|
|
872
913
|
await this.sendCommandAck(frame, "rejected", "activation_redefinition");
|
|
873
914
|
return;
|
|
874
915
|
}
|
|
@@ -884,6 +925,25 @@ export class AgentServiceSandboxClient {
|
|
|
884
925
|
await this.sendCommandAck(frame, "ok");
|
|
885
926
|
return;
|
|
886
927
|
}
|
|
928
|
+
let skillProvider;
|
|
929
|
+
if (hasSkillProvider) {
|
|
930
|
+
try {
|
|
931
|
+
skillProvider = await this.prepareSkillProvider(rawSkillProvider);
|
|
932
|
+
}
|
|
933
|
+
catch (error) {
|
|
934
|
+
const code = error instanceof RuntimeSkillProviderError
|
|
935
|
+
? error.code
|
|
936
|
+
: "skill_provider_prepare_failed";
|
|
937
|
+
await this.sendCommandAck(frame, "rejected", code);
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const requiredBySkills = skillProvider.catalog.flatMap((entry) => entry.requiredCapabilities);
|
|
941
|
+
const missingSkillCapabilities = missingCapabilities(requiredBySkills);
|
|
942
|
+
if (missingSkillCapabilities.length > 0) {
|
|
943
|
+
await this.sendCommandAck(frame, "rejected", `missing_capabilities:${missingSkillCapabilities.join(",")}`);
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
887
947
|
// 同一时刻只允许一个 active session/activation。先撤销上一 workspace 的
|
|
888
948
|
// runtime 访问并等待进程退出,再暴露新 workspace,避免同 UID 跨 Session 读取。
|
|
889
949
|
const previousSessionId = this.activeSessionId;
|
|
@@ -913,6 +973,8 @@ export class AgentServiceSandboxClient {
|
|
|
913
973
|
runtimeEnv,
|
|
914
974
|
instructions,
|
|
915
975
|
inputAttachmentGrant: attachmentGrant,
|
|
976
|
+
...(skillProvider ? { skillProvider } : {}),
|
|
977
|
+
...(skillGrantKey ? { skillGrantKey } : {}),
|
|
916
978
|
});
|
|
917
979
|
this.activeSessionId = sessionId;
|
|
918
980
|
this.persist();
|
package/dist/cli.d.ts
CHANGED
|
@@ -20,4 +20,5 @@ export interface PollLoopDeps {
|
|
|
20
20
|
log?: Logger;
|
|
21
21
|
}
|
|
22
22
|
export declare function runPollLoop(deps: PollLoopDeps): Promise<PollLoopExit>;
|
|
23
|
+
export declare function assertManagedCourseDaemonVersion(actualVersion: string, selectedVersion: string | undefined): void;
|
|
23
24
|
export declare function runCli(argv: string[]): Promise<number>;
|
package/dist/cli.js
CHANGED
|
@@ -337,6 +337,11 @@ async function readSandboxBootstrapFromStdin() {
|
|
|
337
337
|
chunk.fill(0);
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
|
+
export function assertManagedCourseDaemonVersion(actualVersion, selectedVersion) {
|
|
341
|
+
if (selectedVersion && selectedVersion !== actualVersion) {
|
|
342
|
+
throw new Error("Managed Course Daemon version does not match the selected release");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
340
345
|
async function cmdAgentServiceSession(args) {
|
|
341
346
|
const bootstrap = args.flags["bootstrap-stdin"] === true
|
|
342
347
|
? await readSandboxBootstrapFromStdin()
|
|
@@ -350,6 +355,7 @@ async function cmdAgentServiceSession(args) {
|
|
|
350
355
|
console.error("Agent Service sandbox environment is incomplete");
|
|
351
356
|
return 1;
|
|
352
357
|
}
|
|
358
|
+
assertManagedCourseDaemonVersion(pkg.version, process.env.BOTLEARN_MANAGED_COURSE_DAEMON_VERSION?.trim() || undefined);
|
|
353
359
|
augmentProcessPath();
|
|
354
360
|
const runtimes = new Map();
|
|
355
361
|
for (const mod of RUNTIME_MODULES) {
|
|
@@ -363,6 +369,7 @@ async function cmdAgentServiceSession(args) {
|
|
|
363
369
|
sandboxToken,
|
|
364
370
|
runtimes,
|
|
365
371
|
daemonVersion: pkg.version,
|
|
372
|
+
deepseekTuiVersion: process.env.BOTLEARN_MANAGED_DEEPSEEK_TUI_VERSION?.trim() || undefined,
|
|
366
373
|
});
|
|
367
374
|
clearAgentServiceControlEnv();
|
|
368
375
|
await client.run();
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./log.js";
|
|
|
18
18
|
export * from "./redaction.js";
|
|
19
19
|
export * from "./runtime-profile.js";
|
|
20
20
|
export * from "./runtime-env.js";
|
|
21
|
+
export * from "./runtime-skills.js";
|
|
21
22
|
export * from "./mcp/report-progress.js";
|
|
22
23
|
export * from "./runtimes/index.js";
|
|
23
24
|
export * from "./runtimes/engine.js";
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./log.js";
|
|
|
18
18
|
export * from "./redaction.js";
|
|
19
19
|
export * from "./runtime-profile.js";
|
|
20
20
|
export * from "./runtime-env.js";
|
|
21
|
+
export * from "./runtime-skills.js";
|
|
21
22
|
export * from "./mcp/report-progress.js";
|
|
22
23
|
export * from "./runtimes/index.js";
|
|
23
24
|
export * from "./runtimes/engine.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import net from "node:net";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
export function runCourseSkillsRelay(argv = process.argv.slice(2)) {
|
|
7
|
+
const socketPath = relaySocketPath(argv);
|
|
8
|
+
const socket = net.createConnection({ path: socketPath });
|
|
9
|
+
const fail = () => {
|
|
10
|
+
process.stderr.write("course_skills relay unavailable\n");
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
};
|
|
13
|
+
socket.once("error", fail);
|
|
14
|
+
socket.once("connect", () => {
|
|
15
|
+
process.stdin.pipe(socket);
|
|
16
|
+
socket.pipe(process.stdout);
|
|
17
|
+
});
|
|
18
|
+
socket.once("close", () => {
|
|
19
|
+
if (!process.stdin.readableEnded)
|
|
20
|
+
process.stdin.destroy();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function relaySocketPath(argv) {
|
|
24
|
+
if (argv.length !== 2 || argv[0] !== "--socket") {
|
|
25
|
+
throw new Error("course_skills relay requires --socket");
|
|
26
|
+
}
|
|
27
|
+
const value = argv[1] ?? "";
|
|
28
|
+
if (!path.isAbsolute(value)
|
|
29
|
+
|| value.includes("\0")
|
|
30
|
+
|| Buffer.byteLength(value, "utf8") > 240) {
|
|
31
|
+
throw new Error("course_skills relay socket is invalid");
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
function isMainModule() {
|
|
36
|
+
const entry = process.argv[1];
|
|
37
|
+
if (!entry)
|
|
38
|
+
return false;
|
|
39
|
+
try {
|
|
40
|
+
return realpathSync(entry) === fileURLToPath(import.meta.url);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (isMainModule()) {
|
|
47
|
+
try {
|
|
48
|
+
runCourseSkillsRelay();
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
process.stderr.write("course_skills relay configuration invalid\n");
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type PreparedRuntimeSkillProvider, type RuntimeSkillCatalogEntry, type RuntimeSkillEvent } from "../runtime-skills.js";
|
|
2
|
+
type JsonRpcId = string | number | null;
|
|
3
|
+
interface JsonRpcRequest {
|
|
4
|
+
jsonrpc?: unknown;
|
|
5
|
+
id?: unknown;
|
|
6
|
+
method?: unknown;
|
|
7
|
+
params?: unknown;
|
|
8
|
+
}
|
|
9
|
+
interface JsonRpcResponse {
|
|
10
|
+
jsonrpc: "2.0";
|
|
11
|
+
id: JsonRpcId;
|
|
12
|
+
result?: unknown;
|
|
13
|
+
error?: {
|
|
14
|
+
code: number;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface CourseSkillsMcpServer {
|
|
19
|
+
socketPath: string;
|
|
20
|
+
catalog: RuntimeSkillCatalogEntry[];
|
|
21
|
+
markApplied(): Promise<void>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export interface CourseSkillsMcpServerOptions {
|
|
25
|
+
prepared: PreparedRuntimeSkillProvider;
|
|
26
|
+
onEvent(event: RuntimeSkillEvent): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Managed Agent Service root. `undefined` auto-detects it; `null` is only for
|
|
29
|
+
* private same-UID tests/BYOA experiments.
|
|
30
|
+
*/
|
|
31
|
+
managedRoot?: string | null;
|
|
32
|
+
}
|
|
33
|
+
export declare class CourseSkillsMcpRuntime {
|
|
34
|
+
private readonly options;
|
|
35
|
+
private readonly grantsByRef;
|
|
36
|
+
private readonly loadedSkills;
|
|
37
|
+
private readonly loadedReferences;
|
|
38
|
+
private referenceBytes;
|
|
39
|
+
constructor(options: CourseSkillsMcpServerOptions);
|
|
40
|
+
emitAppliedEvents(): Promise<void>;
|
|
41
|
+
handle(request: JsonRpcRequest): Promise<JsonRpcResponse | null>;
|
|
42
|
+
private loadSkill;
|
|
43
|
+
private loadReference;
|
|
44
|
+
private requireGrant;
|
|
45
|
+
private emit;
|
|
46
|
+
private emitLoadFailed;
|
|
47
|
+
}
|
|
48
|
+
export declare function startCourseSkillsMcpServer(options: CourseSkillsMcpServerOptions): Promise<CourseSkillsMcpServer>;
|
|
49
|
+
export {};
|