openlearn-next 0.2.5 → 0.2.7
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 +34 -136
- package/dist/assets/{CloudDriveModal-DgDurUBT.js → CloudDriveModal-TFWlPh8x.js} +1 -1
- package/dist/assets/{Dashboard-BnF7YAQi.js → Dashboard-vSYAYoji.js} +2 -2
- package/dist/assets/{HelpView-BP581QYZ.js → HelpView-D3WIxMoB.js} +2 -2
- package/dist/assets/{InteractiveCoursewareViewer-EIRNulEo.js → InteractiveCoursewareViewer-01PS40_x.js} +1 -1
- package/dist/assets/{InteractiveWhiteboard-D360IHbP.js → InteractiveWhiteboard-bmT1LKD6.js} +8 -8
- package/dist/assets/{LazyCourseware-qE4CY67E.js → LazyCourseware-Bcxn_20f.js} +1 -1
- package/dist/assets/{LazyWhiteboard-B5JmqHZ5.js → LazyWhiteboard-CJA7aRIM.js} +1 -1
- package/dist/assets/{LessonEditorView-C0czhtmf.js → LessonEditorView-hdJblhmb.js} +1 -1
- package/dist/assets/{LiveClassroomView-CrTY3jhP.js → LiveClassroomView-ByyIOLJC.js} +1 -1
- package/dist/assets/{PluginView-QS2b6nSF.js → PluginView-B3ZolNGQ.js} +2 -2
- package/dist/assets/{StudentAssignmentView-YxVJ5wkl.js → StudentAssignmentView-DDY7C092.js} +1 -1
- package/dist/assets/{StudentLessonView-D1gYdLM1.js → StudentLessonView-BcQ7q4QF.js} +1 -1
- package/dist/assets/{StudentPreviewModal-CG8bgUeI.js → StudentPreviewModal-ETJBF1Vc.js} +1 -1
- package/dist/assets/{StudentView-CmSL3cDw.js → StudentView-BOqPntx-.js} +1 -1
- package/dist/assets/{SystemResourceLibraryModal-Dnh7F5Vm.js → SystemResourceLibraryModal-tg8xnblT.js} +1 -1
- package/dist/assets/{TeacherView-BqXb0izg.js → TeacherView-CrbllHIm.js} +1 -1
- package/dist/assets/{index-Cq_aKTfc.js → index-CDTw8wSY.js} +1 -1
- package/dist/assets/index-eXp-qZdm.js +129 -0
- package/dist/index.html +1 -1
- package/dist/server.cjs +100 -37
- package/package.json +1 -1
- package/dist/assets/index-BxA9vp--.js +0 -129
package/dist/index.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
</script>
|
|
18
|
-
<script type="module" crossorigin src="/assets/index-
|
|
18
|
+
<script type="module" crossorigin src="/assets/index-eXp-qZdm.js"></script>
|
|
19
19
|
<link rel="stylesheet" crossorigin href="/assets/index-CATki2cp.css">
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
package/dist/server.cjs
CHANGED
|
@@ -2659,6 +2659,21 @@ parentPort.on('message', async function(msg) {
|
|
|
2659
2659
|
},
|
|
2660
2660
|
db: dbApi,
|
|
2661
2661
|
require: function(moduleName) {
|
|
2662
|
+
var BLOCKED_NATIVE_MODULES = [
|
|
2663
|
+
'child_process', 'node:child_process',
|
|
2664
|
+
'fs', 'node:fs', 'fs/promises', 'node:fs/promises',
|
|
2665
|
+
'net', 'node:net',
|
|
2666
|
+
'http', 'node:http', 'https', 'node:https', 'http2', 'node:http2',
|
|
2667
|
+
'dgram', 'node:dgram', 'dns', 'node:dns',
|
|
2668
|
+
'cluster', 'node:cluster',
|
|
2669
|
+
'worker_threads', 'node:worker_threads',
|
|
2670
|
+
'vm', 'node:vm',
|
|
2671
|
+
'v8', 'node:v8',
|
|
2672
|
+
'wasi', 'node:wasi'
|
|
2673
|
+
];
|
|
2674
|
+
if (BLOCKED_NATIVE_MODULES.indexOf(moduleName) !== -1) {
|
|
2675
|
+
throw new Error('[SecurityError] Direct access to Node.js native module "' + moduleName + '" is forbidden in plugin worker sandbox.');
|
|
2676
|
+
}
|
|
2662
2677
|
if (PLUGIN_SHARED_MODULES.indexOf(moduleName) !== -1) {
|
|
2663
2678
|
try {
|
|
2664
2679
|
return requireFn(moduleName);
|
|
@@ -3374,7 +3389,16 @@ var CapabilityGuard = class {
|
|
|
3374
3389
|
constructor() {
|
|
3375
3390
|
this.actorCapabilities = /* @__PURE__ */ new Map();
|
|
3376
3391
|
this.actorCapabilities.set("user-demo", ["*:*:*"]);
|
|
3377
|
-
this.actorCapabilities.set("user-frontend", [
|
|
3392
|
+
this.actorCapabilities.set("user-frontend", [
|
|
3393
|
+
"lesson:*",
|
|
3394
|
+
"whiteboard:*",
|
|
3395
|
+
"management:*",
|
|
3396
|
+
"quiz:*",
|
|
3397
|
+
"vfs:*",
|
|
3398
|
+
"process:*",
|
|
3399
|
+
"plugin:*"
|
|
3400
|
+
]);
|
|
3401
|
+
this.actorCapabilities.set("anonymous", []);
|
|
3378
3402
|
this.actorCapabilities.set("agent-system-0", [
|
|
3379
3403
|
"lesson:write",
|
|
3380
3404
|
"lesson:delete",
|
|
@@ -3388,8 +3412,8 @@ var CapabilityGuard = class {
|
|
|
3388
3412
|
"process:write",
|
|
3389
3413
|
"process:read"
|
|
3390
3414
|
]);
|
|
3391
|
-
this.actorCapabilities.set("teacher-demo", ["lesson
|
|
3392
|
-
this.actorCapabilities.set("student-demo", ["student:write"]);
|
|
3415
|
+
this.actorCapabilities.set("teacher-demo", ["lesson:*", "whiteboard:*", "management:*", "quiz:*", "vfs:*"]);
|
|
3416
|
+
this.actorCapabilities.set("student-demo", ["student:write", "lesson:read", "whiteboard:read"]);
|
|
3393
3417
|
}
|
|
3394
3418
|
grant(actorId, cap) {
|
|
3395
3419
|
const caps = this.actorCapabilities.get(actorId) || [];
|
|
@@ -3402,8 +3426,28 @@ var CapabilityGuard = class {
|
|
|
3402
3426
|
this.actorCapabilities.delete(actorId);
|
|
3403
3427
|
}
|
|
3404
3428
|
check(actorId, requiredCap) {
|
|
3405
|
-
const isAdmin = actorId === "role:administrator" || actorId?.endsWith(":administrator") || actorId === "admin-demo";
|
|
3429
|
+
const isAdmin = actorId === "role:administrator" || actorId?.endsWith(":administrator") || actorId === "admin" || actorId === "usr_admin" || actorId === "admin-demo";
|
|
3406
3430
|
if (isAdmin) return true;
|
|
3431
|
+
if (actorId?.endsWith(":teacher")) {
|
|
3432
|
+
const teacherCaps = ["lesson:*", "whiteboard:*", "management:*", "quiz:*", "vfs:*", "process:*", "plugin:*"];
|
|
3433
|
+
const [reqRes2, reqAct2] = requiredCap.split(":");
|
|
3434
|
+
if (teacherCaps.some((c) => {
|
|
3435
|
+
const [res, act] = c.split(":");
|
|
3436
|
+
return (res === reqRes2 || res === "*") && (act === reqAct2 || act === "*");
|
|
3437
|
+
})) {
|
|
3438
|
+
return true;
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
if (actorId?.endsWith(":student")) {
|
|
3442
|
+
const studentCaps = ["student:write", "lesson:read", "whiteboard:read"];
|
|
3443
|
+
const [reqRes2, reqAct2] = requiredCap.split(":");
|
|
3444
|
+
if (studentCaps.some((c) => {
|
|
3445
|
+
const [res, act] = c.split(":");
|
|
3446
|
+
return (res === reqRes2 || res === "*") && (act === reqAct2 || act === "*");
|
|
3447
|
+
})) {
|
|
3448
|
+
return true;
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3407
3451
|
const caps = this.actorCapabilities.get(actorId) || [];
|
|
3408
3452
|
if (caps.includes("*:*:*") || caps.includes("*")) return true;
|
|
3409
3453
|
if (caps.includes(requiredCap)) return true;
|
|
@@ -3638,7 +3682,7 @@ var classroomToolSchema = import_zod.z.object({
|
|
|
3638
3682
|
icon: import_zod.z.string().optional(),
|
|
3639
3683
|
description: import_zod.z.string().optional(),
|
|
3640
3684
|
commandType: import_zod.z.string().min(1),
|
|
3641
|
-
payload: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
3685
|
+
payload: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
|
|
3642
3686
|
});
|
|
3643
3687
|
var contributesSchema = import_zod.z.object({
|
|
3644
3688
|
"classroom.tool": import_zod.z.array(classroomToolSchema).optional(),
|
|
@@ -3665,7 +3709,10 @@ var contributesSchema = import_zod.z.object({
|
|
|
3665
3709
|
label: import_zod.z.string().min(1),
|
|
3666
3710
|
icon: import_zod.z.string().optional()
|
|
3667
3711
|
})).optional()
|
|
3668
|
-
|
|
3712
|
+
// v0.2.6: 锚点槽位(anchor:*)为开放命名空间,由宿主公布锚点 id。
|
|
3713
|
+
// .passthrough() 保留任意 anchor:* 键(运行时透传),避免被 zod 默认 strip。
|
|
3714
|
+
// 锚点条目的运行时校验由前端注册时(ExtensionPointConfig)完成。
|
|
3715
|
+
}).passthrough().optional();
|
|
3669
3716
|
var deploySchema = import_zod.z.object({
|
|
3670
3717
|
script: import_zod.z.string().min(1, { error: "deploy.script \u4E0D\u80FD\u4E3A\u7A7A" }).optional(),
|
|
3671
3718
|
staticRoute: import_zod.z.string().optional(),
|
|
@@ -3689,7 +3736,7 @@ var manifestSchema = import_zod.z.object({
|
|
|
3689
3736
|
pluginDependencies: import_zod.z.array(import_zod.z.string().min(1)).optional(),
|
|
3690
3737
|
provides: import_zod.z.array(import_zod.z.string().min(1)).optional(),
|
|
3691
3738
|
configuration: import_zod.z.object({
|
|
3692
|
-
properties: import_zod.z.record(import_zod.z.object({
|
|
3739
|
+
properties: import_zod.z.record(import_zod.z.string(), import_zod.z.object({
|
|
3693
3740
|
type: import_zod.z.enum(["string", "number", "boolean", "integer"]),
|
|
3694
3741
|
default: import_zod.z.unknown().optional(),
|
|
3695
3742
|
description: import_zod.z.string().optional(),
|
|
@@ -3774,6 +3821,7 @@ if (process.env.OPENLEARN_DB_PATH) {
|
|
|
3774
3821
|
var db = new import_better_sqlite3.default(dbPath);
|
|
3775
3822
|
db.pragma("journal_mode = WAL");
|
|
3776
3823
|
db.pragma("synchronous = NORMAL");
|
|
3824
|
+
db.pragma("foreign_keys = ON");
|
|
3777
3825
|
db.exec(`
|
|
3778
3826
|
CREATE TABLE IF NOT EXISTS events (
|
|
3779
3827
|
id TEXT PRIMARY KEY,
|
|
@@ -4116,6 +4164,17 @@ db.exec(`
|
|
|
4116
4164
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
4117
4165
|
graded_at INTEGER
|
|
4118
4166
|
);
|
|
4167
|
+
|
|
4168
|
+
-- Performance Indexes
|
|
4169
|
+
CREATE INDEX IF NOT EXISTS idx_whiteboard_lesson ON whiteboard_elements(lesson_id);
|
|
4170
|
+
CREATE INDEX IF NOT EXISTS idx_class_students_class ON class_students(class_id);
|
|
4171
|
+
CREATE INDEX IF NOT EXISTS idx_class_students_student ON class_students(student_id);
|
|
4172
|
+
CREATE INDEX IF NOT EXISTS idx_schedules_class_date ON schedules(class_id, scheduled_date);
|
|
4173
|
+
CREATE INDEX IF NOT EXISTS idx_courseware_attempt_cw_st ON courseware_attempt(courseware_id, student_id);
|
|
4174
|
+
CREATE INDEX IF NOT EXISTS idx_submission_result_attempt ON submission_result(attempt_id);
|
|
4175
|
+
CREATE INDEX IF NOT EXISTS idx_events_type_time ON events(type, timestamp);
|
|
4176
|
+
CREATE INDEX IF NOT EXISTS idx_assignments_class ON assignments(class_id);
|
|
4177
|
+
CREATE INDEX IF NOT EXISTS idx_attendance_schedule ON attendance(schedule_id);
|
|
4119
4178
|
`);
|
|
4120
4179
|
try {
|
|
4121
4180
|
db.exec(`ALTER TABLE plugins ADD COLUMN execution_mode TEXT DEFAULT 'inline'`);
|
|
@@ -4250,7 +4309,7 @@ var VfsPlugin = {
|
|
|
4250
4309
|
"@openlearn/core:IDatabase@^1.0.0"
|
|
4251
4310
|
],
|
|
4252
4311
|
capabilitiesProposed: ["vfs:read", "vfs:write"],
|
|
4253
|
-
engines: { openlearn: "^2.5
|
|
4312
|
+
engines: { openlearn: "^0.2.5" }
|
|
4254
4313
|
},
|
|
4255
4314
|
activate: async (ctx) => {
|
|
4256
4315
|
const commandBus = ctx.services.commandBus;
|
|
@@ -4416,7 +4475,7 @@ var ProcessPlugin = {
|
|
|
4416
4475
|
"@openlearn/core:IDatabase@^1.0.0"
|
|
4417
4476
|
],
|
|
4418
4477
|
capabilitiesProposed: ["process:read", "process:write"],
|
|
4419
|
-
engines: { openlearn: "^2.5
|
|
4478
|
+
engines: { openlearn: "^0.2.5" }
|
|
4420
4479
|
},
|
|
4421
4480
|
activate: async (ctx) => {
|
|
4422
4481
|
const commandBus = ctx.services.commandBus;
|
|
@@ -4547,7 +4606,7 @@ var ManagementPlugin = {
|
|
|
4547
4606
|
"@openlearn/core:IDatabase@^1.0.0"
|
|
4548
4607
|
],
|
|
4549
4608
|
capabilitiesProposed: ["class:read", "class:write", "student:read", "student:write"],
|
|
4550
|
-
engines: { openlearn: "^2.5
|
|
4609
|
+
engines: { openlearn: "^0.2.5" }
|
|
4551
4610
|
},
|
|
4552
4611
|
activate: async (ctx) => {
|
|
4553
4612
|
const commandBus = ctx.services.commandBus;
|
|
@@ -5446,7 +5505,7 @@ var AiSubmitInjectorPlugin = {
|
|
|
5446
5505
|
"@openlearn/core:IAIService@^1.0.0"
|
|
5447
5506
|
],
|
|
5448
5507
|
capabilitiesProposed: [],
|
|
5449
|
-
engines: { openlearn: "^2.5
|
|
5508
|
+
engines: { openlearn: "^0.2.5" }
|
|
5450
5509
|
},
|
|
5451
5510
|
activate: async (ctx) => {
|
|
5452
5511
|
const eventBus = ctx.services.eventBus;
|
|
@@ -5538,7 +5597,7 @@ var BuiltinPlugin = {
|
|
|
5538
5597
|
"@openlearn/core:IPluginHost@^1.0.0"
|
|
5539
5598
|
],
|
|
5540
5599
|
capabilitiesProposed: ["lesson:read", "lesson:write", "whiteboard:read", "whiteboard:write"],
|
|
5541
|
-
engines: { openlearn: "^2.5
|
|
5600
|
+
engines: { openlearn: "^0.2.5" }
|
|
5542
5601
|
},
|
|
5543
5602
|
activate: async (ctx) => {
|
|
5544
5603
|
const commandBus = ctx.services.commandBus;
|
|
@@ -6923,7 +6982,7 @@ var AiPlannerPlugin = {
|
|
|
6923
6982
|
"@openlearn/core:IEventBusService@^1.0.0"
|
|
6924
6983
|
],
|
|
6925
6984
|
capabilitiesProposed: ["process:write", "lesson:write", "assignment:write"],
|
|
6926
|
-
engines: { openlearn: "^2.5
|
|
6985
|
+
engines: { openlearn: "^0.2.5" }
|
|
6927
6986
|
},
|
|
6928
6987
|
activate: async (ctx) => {
|
|
6929
6988
|
const commandBus = ctx.services.commandBus;
|
|
@@ -7109,7 +7168,7 @@ var AssignmentEvalPlugin = {
|
|
|
7109
7168
|
"@openlearn/core:ISemesterGradeService@^1.0.0"
|
|
7110
7169
|
],
|
|
7111
7170
|
capabilitiesProposed: ["lesson:read", "lesson:write"],
|
|
7112
|
-
engines: { openlearn: "^2.5
|
|
7171
|
+
engines: { openlearn: "^0.2.5" }
|
|
7113
7172
|
},
|
|
7114
7173
|
activate: async (ctx) => {
|
|
7115
7174
|
const commandBus = ctx.services.commandBus;
|
|
@@ -7695,7 +7754,7 @@ var ContributionRegistry = class {
|
|
|
7695
7754
|
register(pluginId, contributes) {
|
|
7696
7755
|
this.unregister(pluginId);
|
|
7697
7756
|
for (const [slot, configs] of Object.entries(contributes)) {
|
|
7698
|
-
if (!configs || configs.length === 0) continue;
|
|
7757
|
+
if (!Array.isArray(configs) || configs.length === 0) continue;
|
|
7699
7758
|
if (!this.contributions.has(slot)) {
|
|
7700
7759
|
this.contributions.set(slot, /* @__PURE__ */ new Map());
|
|
7701
7760
|
}
|
|
@@ -8057,7 +8116,7 @@ var PluginRuntimeComposition = class {
|
|
|
8057
8116
|
this.workerManager = workerManager;
|
|
8058
8117
|
this.id = "srv_plugin_runtime_composition";
|
|
8059
8118
|
this.name = "PluginRuntimeComposition";
|
|
8060
|
-
this.version = "0.2.
|
|
8119
|
+
this.version = "0.2.5";
|
|
8061
8120
|
this._isStarted = false;
|
|
8062
8121
|
}
|
|
8063
8122
|
get isStarted() {
|
|
@@ -8111,7 +8170,7 @@ var PluginLifecycleManager = class {
|
|
|
8111
8170
|
this.pluginHost = pluginHost;
|
|
8112
8171
|
this.id = "srv_plugin_lifecycle_manager";
|
|
8113
8172
|
this.name = "PluginLifecycleManager";
|
|
8114
|
-
this.version = "0.2.
|
|
8173
|
+
this.version = "0.2.5";
|
|
8115
8174
|
}
|
|
8116
8175
|
getPluginState(pluginId) {
|
|
8117
8176
|
return this.pluginHost.getPluginState(pluginId);
|
|
@@ -8158,7 +8217,7 @@ var PluginCapabilityGateway = class {
|
|
|
8158
8217
|
this.capabilityRegistry = capabilityRegistry;
|
|
8159
8218
|
this.id = "srv_plugin_capability_gateway";
|
|
8160
8219
|
this.name = "PluginCapabilityGateway";
|
|
8161
|
-
this.version = "0.2.
|
|
8220
|
+
this.version = "0.2.5";
|
|
8162
8221
|
}
|
|
8163
8222
|
listCapabilities() {
|
|
8164
8223
|
const rawCaps = this.capabilityRegistry.listCapabilities();
|
|
@@ -8212,7 +8271,7 @@ var UnifiedExtensionRegistry = class {
|
|
|
8212
8271
|
constructor() {
|
|
8213
8272
|
this.id = "srv_unified_extension_registry";
|
|
8214
8273
|
this.name = "UnifiedExtensionRegistry";
|
|
8215
|
-
this.version = "0.2.
|
|
8274
|
+
this.version = "0.2.5";
|
|
8216
8275
|
this._extensions = /* @__PURE__ */ new Map();
|
|
8217
8276
|
}
|
|
8218
8277
|
registerExtension(category, id, impl, meta) {
|
|
@@ -8317,7 +8376,7 @@ var PluginDistributionManager = class {
|
|
|
8317
8376
|
this.pluginHost = pluginHost;
|
|
8318
8377
|
this.id = "srv_plugin_distribution_manager";
|
|
8319
8378
|
this.name = "PluginDistributionManager";
|
|
8320
|
-
this.version = "0.2.
|
|
8379
|
+
this.version = "0.2.5";
|
|
8321
8380
|
this._repositories = /* @__PURE__ */ new Map();
|
|
8322
8381
|
}
|
|
8323
8382
|
registerRepository(repo) {
|
|
@@ -8406,7 +8465,7 @@ function validatePluginStateTransition(currentState, nextState, pluginId) {
|
|
|
8406
8465
|
}
|
|
8407
8466
|
var ACTIVATION_TIMEOUT_MS = 5e3;
|
|
8408
8467
|
var DEACTIVATION_TIMEOUT_MS = 5e3;
|
|
8409
|
-
var OPENLEARN_VERSION = "0.2.
|
|
8468
|
+
var OPENLEARN_VERSION = "0.2.5";
|
|
8410
8469
|
var PluginHost = class {
|
|
8411
8470
|
constructor(serviceRegistry, esmLoader, db2, pluginsDir) {
|
|
8412
8471
|
this.serviceRegistry = serviceRegistry;
|
|
@@ -10431,7 +10490,7 @@ var HotReloadController = class {
|
|
|
10431
10490
|
}
|
|
10432
10491
|
if (this.enabled) return;
|
|
10433
10492
|
this.enabled = true;
|
|
10434
|
-
await this.fileWatcher.startWatch(this.watchDir, (event) => {
|
|
10493
|
+
await this.fileWatcher.startWatch(this.watchDir, async (event) => {
|
|
10435
10494
|
this.handleFileChange(event.pluginId, event.filePath);
|
|
10436
10495
|
});
|
|
10437
10496
|
console.log("[HotReload] Hot reload enabled \u2014 watching for plugin changes");
|
|
@@ -16020,7 +16079,7 @@ var StartupTimeoutError = class extends PlatformBootstrapError {
|
|
|
16020
16079
|
this.name = "StartupTimeoutError";
|
|
16021
16080
|
}
|
|
16022
16081
|
};
|
|
16023
|
-
var PLATFORM_VERSION = "0.2.
|
|
16082
|
+
var PLATFORM_VERSION = "0.2.5";
|
|
16024
16083
|
var BOOTSTRAP_STAGE_NAMES = Object.freeze([
|
|
16025
16084
|
"Created" /* Created */,
|
|
16026
16085
|
"Configuring" /* Configuring */,
|
|
@@ -16722,10 +16781,10 @@ var PluginCompositionModule = class {
|
|
|
16722
16781
|
const realPluginHost = options?.infrastructureRefs?.get("pluginHost") ?? { name: "PluginHostService", isReady: true, pluginsCount: 0 };
|
|
16723
16782
|
const realContributionRegistry = options?.infrastructureRefs?.get("contributionRegistry") ?? { name: "ContributionRegistry", slotsCount: 0 };
|
|
16724
16783
|
const realRuntimeComposition = options?.infrastructureRefs?.get("runtimeComposition") ?? { name: "PluginRuntimeComposition", isStarted: true };
|
|
16725
|
-
const realLifecycleManager = options?.infrastructureRefs?.get("lifecycleManager") ?? { name: "PluginLifecycleManager", version: "2.5
|
|
16726
|
-
const realCapabilityGateway = options?.infrastructureRefs?.get("capabilityGateway") ?? { name: "PluginCapabilityGateway", version: "2.5
|
|
16727
|
-
const realExtensionRegistry = options?.infrastructureRefs?.get("extensionRegistry") ?? { name: "UnifiedExtensionRegistry", version: "2.5
|
|
16728
|
-
const realDistributionManager = options?.infrastructureRefs?.get("distributionManager") ?? { name: "PluginDistributionManager", version: "2.5
|
|
16784
|
+
const realLifecycleManager = options?.infrastructureRefs?.get("lifecycleManager") ?? { name: "PluginLifecycleManager", version: "0.2.5" };
|
|
16785
|
+
const realCapabilityGateway = options?.infrastructureRefs?.get("capabilityGateway") ?? { name: "PluginCapabilityGateway", version: "0.2.5" };
|
|
16786
|
+
const realExtensionRegistry = options?.infrastructureRefs?.get("extensionRegistry") ?? { name: "UnifiedExtensionRegistry", version: "0.2.5" };
|
|
16787
|
+
const realDistributionManager = options?.infrastructureRefs?.get("distributionManager") ?? { name: "PluginDistributionManager", version: "0.2.5" };
|
|
16729
16788
|
registerOrReplace({
|
|
16730
16789
|
id: "srv_plugin_host",
|
|
16731
16790
|
lifetime: "Singleton",
|
|
@@ -16893,7 +16952,7 @@ var Kernel = class {
|
|
|
16893
16952
|
throw new Error(`[PayloadValidationError] Invalid command payload for ${command.type}: ${errors.join("; ")}`);
|
|
16894
16953
|
}
|
|
16895
16954
|
}
|
|
16896
|
-
const isAdmin = command.actorId === "role:administrator" || command.actorId === "admin" || command.actorId === "usr_admin" || command.actorId === "admin-demo" || command.actorId?.endsWith(":administrator") || command.actorId?.endsWith(":admin")
|
|
16955
|
+
const isAdmin = command.actorId === "role:administrator" || command.actorId === "admin" || command.actorId === "usr_admin" || command.actorId === "admin-demo" || command.actorId?.endsWith(":administrator") || command.actorId?.endsWith(":admin");
|
|
16897
16956
|
if (action.capabilityRequired && !isAdmin) {
|
|
16898
16957
|
const allowed = this.capabilityGuard.check(command.actorId, action.capabilityRequired);
|
|
16899
16958
|
if (!allowed) {
|
|
@@ -18367,10 +18426,10 @@ function getCookieToken(req) {
|
|
|
18367
18426
|
}
|
|
18368
18427
|
function getActorId(req) {
|
|
18369
18428
|
const token = getCookieToken(req);
|
|
18370
|
-
if (!token) return "
|
|
18429
|
+
if (!token) return "anonymous";
|
|
18371
18430
|
try {
|
|
18372
18431
|
const session = getValidSession(token);
|
|
18373
|
-
if (!session) return "
|
|
18432
|
+
if (!session) return "anonymous";
|
|
18374
18433
|
let role = session.subRole || session.role;
|
|
18375
18434
|
if (session.username === "admin" || session.userId === "usr_admin" || role === "admin" || role === "administrator") {
|
|
18376
18435
|
role = "administrator";
|
|
@@ -18378,9 +18437,9 @@ function getActorId(req) {
|
|
|
18378
18437
|
if (role) {
|
|
18379
18438
|
return `user:${session.userId || "demo"}:${role}`;
|
|
18380
18439
|
}
|
|
18381
|
-
return "
|
|
18440
|
+
return "anonymous";
|
|
18382
18441
|
} catch {
|
|
18383
|
-
return "
|
|
18442
|
+
return "anonymous";
|
|
18384
18443
|
}
|
|
18385
18444
|
}
|
|
18386
18445
|
function requireAuth(...roles) {
|
|
@@ -19163,7 +19222,7 @@ function registerOsRoutes(ctx) {
|
|
|
19163
19222
|
res.status(500).json({ error: e.message });
|
|
19164
19223
|
}
|
|
19165
19224
|
});
|
|
19166
|
-
app.post("/api/commands", async (req, res) => {
|
|
19225
|
+
app.post("/api/commands", requireAuth(), async (req, res) => {
|
|
19167
19226
|
try {
|
|
19168
19227
|
const { commandType, payload } = req.body;
|
|
19169
19228
|
const cmd = kernelContainer.commandBus.createCommand(
|
|
@@ -23078,7 +23137,7 @@ function registerGradingRoutes(ctx) {
|
|
|
23078
23137
|
if (!lessonId || !studentId || grade === void 0) {
|
|
23079
23138
|
return res.status(400).json({ success: false, error: "lessonId, studentId, and grade are required" });
|
|
23080
23139
|
}
|
|
23081
|
-
const gradeService = await kernelContainer.
|
|
23140
|
+
const gradeService = await kernelContainer.serviceRegistry.resolve(ISemesterGradeServiceToken);
|
|
23082
23141
|
await gradeService.saveSemesterGrade(lessonId, studentId, Math.round(Number(grade)));
|
|
23083
23142
|
res.json({ success: true });
|
|
23084
23143
|
} catch (e) {
|
|
@@ -23087,7 +23146,7 @@ function registerGradingRoutes(ctx) {
|
|
|
23087
23146
|
});
|
|
23088
23147
|
app.get("/api/classes/:classId/points-dimensions", async (req, res) => {
|
|
23089
23148
|
try {
|
|
23090
|
-
const dimensionRegistry = await kernelContainer.
|
|
23149
|
+
const dimensionRegistry = await kernelContainer.serviceRegistry.resolve(IPointsDimensionRegistryToken);
|
|
23091
23150
|
const dimensions = dimensionRegistry.listDimensions();
|
|
23092
23151
|
res.json({ success: true, dimensions });
|
|
23093
23152
|
} catch (e) {
|
|
@@ -23104,7 +23163,7 @@ function registerGradingRoutes(ctx) {
|
|
|
23104
23163
|
if (!classId || !dimensionId || deltaPoints === void 0 || !reason) {
|
|
23105
23164
|
return res.status(400).json({ success: false, error: "classId, dimensionId, deltaPoints, and reason are required" });
|
|
23106
23165
|
}
|
|
23107
|
-
const ledgerService = await kernelContainer.
|
|
23166
|
+
const ledgerService = await kernelContainer.serviceRegistry.resolve(IPointsLedgerServiceToken);
|
|
23108
23167
|
const logItem = await ledgerService.addPoints(studentId, classId, dimensionId, Number(deltaPoints), reason, pluginId);
|
|
23109
23168
|
kernelContainer.eventBus.publish({
|
|
23110
23169
|
id: logItem.id,
|
|
@@ -23122,7 +23181,7 @@ function registerGradingRoutes(ctx) {
|
|
|
23122
23181
|
try {
|
|
23123
23182
|
const { studentId } = req.params;
|
|
23124
23183
|
const { classId } = req.query;
|
|
23125
|
-
const ledgerService = await kernelContainer.
|
|
23184
|
+
const ledgerService = await kernelContainer.serviceRegistry.resolve(IPointsLedgerServiceToken);
|
|
23126
23185
|
const logs = await ledgerService.getLogs(studentId, classId);
|
|
23127
23186
|
const summary = await ledgerService.getStudentDimensionSummary(studentId, classId || "");
|
|
23128
23187
|
res.json({ success: true, logs, summary });
|
|
@@ -24013,6 +24072,10 @@ function registerPluginsRoutes(ctx) {
|
|
|
24013
24072
|
if (!cleanUrl.endsWith("/chat/completions")) {
|
|
24014
24073
|
cleanUrl = cleanUrl.endsWith("/") ? cleanUrl + "chat/completions" : cleanUrl + "/chat/completions";
|
|
24015
24074
|
}
|
|
24075
|
+
const urlSafety = isSafeExternalUrl(cleanUrl);
|
|
24076
|
+
if (!urlSafety.safe) {
|
|
24077
|
+
return res.status(400).json({ error: `Blocked unsafe AI provider URL: ${urlSafety.reason}` });
|
|
24078
|
+
}
|
|
24016
24079
|
const response = await fetch(cleanUrl, {
|
|
24017
24080
|
method: "POST",
|
|
24018
24081
|
headers: {
|