@agimon-ai/po-loop 0.0.0-alpha.0

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.
@@ -0,0 +1,668 @@
1
+ import { t as DOOM_LOOP_LAUNCHERS_SERVICE } from "../loopLaunchers-CskBMAKF.mjs";
2
+ import { composeServerProviderOverrides, defineServerPlugin, defineTool, readPackageResource } from "@agimon-ai/po-core/serverFacet";
3
+ import { composeRootHooks, defineRoot, defineRoutedContribution, defineTool as defineTool$1 } from "@agimon-ai/po-core/extensionFile";
4
+ import { defineMinorMode, serverMinorModes } from "@agimon-ai/po-minor-mode";
5
+ import { Cron } from "croner";
6
+ import { Type } from "typebox";
7
+ import { Check } from "typebox/value";
8
+ //#region src/constants/loop.ts
9
+ const LIST_COMMAND_NAME = "loops";
10
+ //#endregion
11
+ //#region src/constants/piLoop.ts
12
+ const PACKAGE_SOURCE = "@agimon-ai/po-loop";
13
+ const MODE_STATUS_ID = "loop";
14
+ //#endregion
15
+ //#region src/schemas/loopTools.ts
16
+ const LoopListSchema = Type.Object({}, { additionalProperties: false });
17
+ const LoopStartSchema = Type.Object({
18
+ launcherId: Type.String({
19
+ minLength: 1,
20
+ maxLength: 256
21
+ }),
22
+ instanceId: Type.Optional(Type.String({
23
+ minLength: 1,
24
+ maxLength: 256
25
+ })),
26
+ input: Type.Record(Type.String(), Type.Unknown())
27
+ }, { additionalProperties: false });
28
+ const LoopStopSchema = Type.Object({
29
+ instanceId: Type.String({
30
+ minLength: 1,
31
+ maxLength: 256
32
+ }),
33
+ reason: Type.Optional(Type.String({
34
+ minLength: 1,
35
+ maxLength: 512
36
+ }))
37
+ }, { additionalProperties: false });
38
+ const IntervalLoopSchema = Type.Object({
39
+ prompt: Type.String({
40
+ minLength: 1,
41
+ maxLength: 32768
42
+ }),
43
+ intervalSeconds: Type.Integer({
44
+ minimum: 30,
45
+ maximum: 3600
46
+ })
47
+ }, { additionalProperties: false });
48
+ const CronLoopSchema = Type.Object({
49
+ prompt: Type.String({
50
+ minLength: 1,
51
+ maxLength: 32768
52
+ }),
53
+ cron: Type.String({
54
+ minLength: 1,
55
+ maxLength: 256
56
+ }),
57
+ timezone: Type.Optional(Type.String({
58
+ minLength: 1,
59
+ maxLength: 128
60
+ }))
61
+ }, { additionalProperties: false });
62
+ function parseIntervalLoop(input) {
63
+ if (!Check(IntervalLoopSchema, input) || !input.prompt.trim()) throw new Error("Provide a non-empty prompt and an integer intervalSeconds between 30 and 3600.");
64
+ return {
65
+ ...input,
66
+ prompt: input.prompt.trim()
67
+ };
68
+ }
69
+ function parseCronLoop(input) {
70
+ if (!Check(CronLoopSchema, input) || !input.prompt.trim() || input.cron.trim().split(/\s+/u).length !== 5) throw new Error("Provide a non-empty prompt and a five-field cron expression, with an optional IANA timezone.");
71
+ const timezone = input.timezone ?? "UTC";
72
+ new Intl.DateTimeFormat("en", { timeZone: timezone }).format();
73
+ return {
74
+ ...input,
75
+ prompt: input.prompt.trim(),
76
+ cron: input.cron.trim(),
77
+ timezone
78
+ };
79
+ }
80
+ //#endregion
81
+ //#region src/types/loopView.ts
82
+ /** The browser-only status that carries active Loop instances into the activity dock. */
83
+ const LOOP_VIEW_STATUS_KEY = "doom-loop-instances";
84
+ new RegExp(String.raw`\u001b\[[0-9;]*m`, "gu");
85
+ /** Projects runtime snapshots into the JSON status consumed by the web plugin. */
86
+ function formatLoopStatusView(instances) {
87
+ if (instances.length === 0) return "";
88
+ return JSON.stringify(instances.map((instance) => ({
89
+ instanceId: instance.instanceId,
90
+ label: instance.label ?? instance.launcherLabel,
91
+ detail: instance.detail ?? instance.instanceId,
92
+ state: instance.state
93
+ })));
94
+ }
95
+ //#endregion
96
+ //#region src/services/loopLaunchers/index.ts
97
+ const MAX_ID_LENGTH = 256;
98
+ const MAX_GENERATION_LENGTH = 256;
99
+ const LAUNCHER_ID_LABEL = "loop launcher id";
100
+ const INSTANCE_ID_LABEL = "loop instance id";
101
+ function validId(value, label) {
102
+ if (typeof value !== "string") throw new TypeError(`Invalid ${label}.`);
103
+ const normalized = value.trim();
104
+ let hasControl = false;
105
+ for (const character of normalized) {
106
+ const code = character.codePointAt(0);
107
+ if (code !== void 0 && (code <= 31 || code === 127)) {
108
+ hasControl = true;
109
+ break;
110
+ }
111
+ }
112
+ if (!normalized || normalized.length > MAX_ID_LENGTH || hasControl) throw new Error(`Invalid ${label}.`);
113
+ return normalized;
114
+ }
115
+ function snapshot(entry) {
116
+ return {
117
+ instanceId: entry.instanceId,
118
+ launcherId: entry.launcher.definition.id,
119
+ launcherLabel: entry.launcher.definition.label,
120
+ ...entry.handle?.label ? { label: entry.handle.label } : {},
121
+ ...entry.handle?.detail ? { detail: entry.handle.detail } : {},
122
+ state: entry.state,
123
+ ...entry.startedAt ? { startedAt: entry.startedAt } : {}
124
+ };
125
+ }
126
+ /** Creates the provider-owned launcher registry for one active Doom session. */
127
+ function createDoomLoopLaunchersService({ generation, createInstanceId, timestamp }) {
128
+ if (!generation || generation.length > MAX_GENERATION_LENGTH) throw new TypeError("Doom loop launchers require a valid generation.");
129
+ const launchers = /* @__PURE__ */ new Map();
130
+ const instances = /* @__PURE__ */ new Map();
131
+ const listeners = /* @__PURE__ */ new Set();
132
+ let registrationSequence = 0;
133
+ let disposed = false;
134
+ const ensureActive = () => {
135
+ if (disposed) throw new Error("The Doom loop-launchers service is disposed.");
136
+ };
137
+ const notify = () => {
138
+ for (const listener of listeners) listener();
139
+ };
140
+ const stopEntry = async (entry, reason) => {
141
+ if (instances.get(entry.instanceId) !== entry) return;
142
+ entry.state = "stopping";
143
+ entry.abortController.abort(reason);
144
+ notify();
145
+ try {
146
+ await entry.handle?.stop(reason);
147
+ } finally {
148
+ if (instances.get(entry.instanceId) === entry) instances.delete(entry.instanceId);
149
+ notify();
150
+ }
151
+ };
152
+ return Object.freeze({
153
+ generation,
154
+ register(definition) {
155
+ ensureActive();
156
+ const id = validId(definition.id, LAUNCHER_ID_LABEL);
157
+ if (launchers.has(id)) throw new Error(`Loop launcher '${id}' is already registered.`);
158
+ const token = Symbol(id);
159
+ const entry = {
160
+ token,
161
+ definition: {
162
+ ...definition,
163
+ id
164
+ }
165
+ };
166
+ launchers.set(id, entry);
167
+ registrationSequence += 1;
168
+ notify();
169
+ let registrationDisposed = false;
170
+ return Object.freeze({
171
+ id,
172
+ generation: `${generation}:launcher:${registrationSequence}`,
173
+ async dispose(reason = "Loop launcher disposed.") {
174
+ if (registrationDisposed) return;
175
+ registrationDisposed = true;
176
+ if (launchers.get(id)?.token !== token) return;
177
+ launchers.delete(id);
178
+ const owned = [...instances.values()].filter((instance) => instance.launcher.token === token);
179
+ await Promise.allSettled(owned.map((instance) => stopEntry(instance, reason)));
180
+ notify();
181
+ }
182
+ });
183
+ },
184
+ listLaunchers() {
185
+ ensureActive();
186
+ return [...launchers.values()].map(({ definition }) => ({
187
+ id: definition.id,
188
+ source: definition.source,
189
+ label: definition.label,
190
+ ...definition.description ? { description: definition.description } : {},
191
+ ...definition.inputSchema ? { inputSchema: definition.inputSchema } : {}
192
+ })).sort((left, right) => left.label.localeCompare(right.label) || left.id.localeCompare(right.id));
193
+ },
194
+ listInstances() {
195
+ ensureActive();
196
+ return [...instances.values()].map(snapshot).sort((left, right) => left.instanceId.localeCompare(right.instanceId));
197
+ },
198
+ subscribe(listener) {
199
+ ensureActive();
200
+ listeners.add(listener);
201
+ let subscribed = true;
202
+ return () => {
203
+ if (!subscribed) return;
204
+ subscribed = false;
205
+ listeners.delete(listener);
206
+ };
207
+ },
208
+ async launch(launcherId, options) {
209
+ ensureActive();
210
+ options?.signal?.throwIfAborted();
211
+ const normalizedLauncherId = validId(launcherId, LAUNCHER_ID_LABEL);
212
+ const launcher = launchers.get(normalizedLauncherId);
213
+ if (!launcher) throw new Error(`Loop launcher '${normalizedLauncherId}' is unavailable.`);
214
+ const instanceId = validId(options?.instanceId ?? createInstanceId(), INSTANCE_ID_LABEL);
215
+ if (instances.has(instanceId)) throw new Error(`Loop instance '${instanceId}' already exists.`);
216
+ const entry = {
217
+ instanceId,
218
+ launcher,
219
+ abortController: new AbortController(),
220
+ state: "starting"
221
+ };
222
+ const abortSetup = () => entry.abortController.abort(options?.signal?.reason);
223
+ options?.signal?.addEventListener("abort", abortSetup, { once: true });
224
+ instances.set(instanceId, entry);
225
+ notify();
226
+ try {
227
+ if (options?.interactive === false && !launcher.definition.inputSchema) throw new Error(`Loop launcher '${normalizedLauncherId}' requires manual setup in Activity.`);
228
+ const handle = await launcher.definition.launch({
229
+ instanceId,
230
+ signal: entry.abortController.signal,
231
+ ...options?.input === void 0 ? {} : { input: options.input },
232
+ ...options?.interactive === void 0 ? {} : { interactive: options.interactive }
233
+ });
234
+ const active = !disposed && instances.get(instanceId) === entry && !entry.abortController.signal.aborted;
235
+ if (!handle) {
236
+ if (instances.get(instanceId) === entry) instances.delete(instanceId);
237
+ notify();
238
+ return;
239
+ }
240
+ if (!active || handle.instanceId !== instanceId) {
241
+ await handle.stop(active ? "Loop launcher returned a mismatched instance id." : "Loop launch was cancelled.");
242
+ if (instances.get(instanceId) === entry) instances.delete(instanceId);
243
+ notify();
244
+ if (active) throw new Error(`Loop launcher '${normalizedLauncherId}' returned a mismatched instance id.`);
245
+ return;
246
+ }
247
+ entry.handle = handle;
248
+ entry.state = "running";
249
+ entry.startedAt = timestamp();
250
+ notify();
251
+ return snapshot(entry);
252
+ } catch (error) {
253
+ const cancelled = entry.abortController.signal.aborted || disposed;
254
+ if (instances.get(instanceId) === entry) instances.delete(instanceId);
255
+ notify();
256
+ if (cancelled) return void 0;
257
+ throw error;
258
+ } finally {
259
+ options?.signal?.removeEventListener("abort", abortSetup);
260
+ }
261
+ },
262
+ async stop(instanceId, reason) {
263
+ ensureActive();
264
+ const entry = instances.get(validId(instanceId, INSTANCE_ID_LABEL));
265
+ if (!entry) return false;
266
+ await stopEntry(entry, reason);
267
+ return true;
268
+ },
269
+ async stopAll(reason) {
270
+ if (disposed && instances.size === 0) return;
271
+ await Promise.allSettled([...instances.values()].map((entry) => stopEntry(entry, reason)));
272
+ },
273
+ async dispose(reason = "Doom loop-launchers service disposed.") {
274
+ if (disposed) return;
275
+ disposed = true;
276
+ launchers.clear();
277
+ await Promise.allSettled([...instances.values()].map((entry) => stopEntry(entry, reason)));
278
+ listeners.clear();
279
+ }
280
+ });
281
+ }
282
+ //#endregion
283
+ //#region src/services/loopTools/index.ts
284
+ function result(details) {
285
+ return {
286
+ content: [{
287
+ type: "text",
288
+ text: JSON.stringify(details, null, 2)
289
+ }],
290
+ details
291
+ };
292
+ }
293
+ function createLoopTools(launchers, assertEnabled) {
294
+ return [
295
+ defineTool({
296
+ name: "loop_list",
297
+ label: "List loops",
298
+ description: "List active session loops and available launcher types with their configuration schemas.",
299
+ parameters: LoopListSchema,
300
+ async execute(input, { signal }) {
301
+ assertEnabled();
302
+ signal?.throwIfAborted();
303
+ if (!Check(LoopListSchema, input)) throw new Error("loop_list takes no arguments.");
304
+ const service = launchers();
305
+ return result({
306
+ launchers: service.listLaunchers(),
307
+ instances: service.listInstances()
308
+ });
309
+ }
310
+ }),
311
+ defineTool({
312
+ name: "loop_start",
313
+ label: "Start loop",
314
+ description: "Start a session-scoped loop without operator dialogs. Read loop_list for launcher IDs and input schemas. Loops stop when the session shuts down.",
315
+ parameters: LoopStartSchema,
316
+ executionMode: "serial",
317
+ async execute(input, { signal }) {
318
+ assertEnabled();
319
+ signal?.throwIfAborted();
320
+ if (!Check(LoopStartSchema, input)) throw new Error("Provide launcherId, input, and optionally instanceId.");
321
+ return result(await launchers().launch(input.launcherId, {
322
+ ...input,
323
+ interactive: false,
324
+ signal
325
+ }) ?? { cancelled: true });
326
+ }
327
+ }),
328
+ defineTool({
329
+ name: "loop_stop",
330
+ label: "Stop loop",
331
+ description: "Stop one loop instance owned by the current session. Does not disable Loop mode or stop other loops.",
332
+ parameters: LoopStopSchema,
333
+ executionMode: "serial",
334
+ async execute(input, { signal }) {
335
+ assertEnabled();
336
+ signal?.throwIfAborted();
337
+ if (!Check(LoopStopSchema, input)) throw new Error("Provide instanceId and an optional reason.");
338
+ return result({ stopped: await launchers().stop(input.instanceId, input.reason ?? "Stopped by the agent.") });
339
+ }
340
+ })
341
+ ];
342
+ }
343
+ //#endregion
344
+ //#region src/services/serverRuntime/index.ts
345
+ /** Loops are set by the agent, so a launch always carries its configuration. */
346
+ function prepareLoop(request, cron) {
347
+ if (request.input === void 0) throw new Error("Loop configuration is required. Ask the agent to set the loop.");
348
+ return cron ? parseCronLoop(request.input) : parseIntervalLoop(request.input);
349
+ }
350
+ function createSessionState(host) {
351
+ const launchers = createDoomLoopLaunchersService({
352
+ generation: `${host.context.sessionId}:loop-launchers`,
353
+ createInstanceId: () => crypto.randomUUID(),
354
+ timestamp: () => (/* @__PURE__ */ new Date()).toISOString()
355
+ });
356
+ let disposed = false;
357
+ const modeSelected = () => !disposed && (host.context.selection.state?.["minor-mode"] ?? []).includes("loop");
358
+ const publishView = () => host.context.client.setStatus(LOOP_VIEW_STATUS_KEY, formatLoopStatusView(launchers.listInstances()));
359
+ const modeOwner = defineMinorMode({
360
+ descriptor: {
361
+ source: PACKAGE_SOURCE,
362
+ id: MODE_STATUS_ID,
363
+ label: "Loop",
364
+ description: "Give the agent tools to create, inspect, and stop session loops.",
365
+ order: 60,
366
+ actions: [{
367
+ id: "activate",
368
+ label: "Activate",
369
+ description: "Expose loop tools to the agent.",
370
+ contexts: ["headless"],
371
+ parameters: []
372
+ }, {
373
+ id: "deactivate",
374
+ label: "Deactivate",
375
+ description: "Hide agent loop tools. Existing loops and manual controls remain available.",
376
+ contexts: ["headless"],
377
+ parameters: []
378
+ }]
379
+ },
380
+ state: () => ({
381
+ activation: modeSelected() ? "active" : "inactive",
382
+ condition: "ready",
383
+ ...modeSelected() ? {
384
+ detail: `${launchers.listInstances().length} loops`,
385
+ color: "accent"
386
+ } : {},
387
+ actions: [{
388
+ id: "activate",
389
+ enabled: !modeSelected(),
390
+ ...modeSelected() ? { disabledReason: "Loop mode is already active." } : {}
391
+ }, {
392
+ id: "deactivate",
393
+ enabled: modeSelected(),
394
+ ...modeSelected() ? {} : { disabledReason: "Loop mode is not active." }
395
+ }]
396
+ }),
397
+ async handleAction(_runtime, actionId, _arguments, { signal }) {
398
+ signal.throwIfAborted();
399
+ if (actionId !== "activate" && actionId !== "deactivate") throw new Error(`Unknown loop mode action: ${actionId}`);
400
+ const modes = (host.context.selection.state?.["minor-mode"] ?? []).filter((mode) => mode !== MODE_STATUS_ID);
401
+ await host.changeSelection({
402
+ axis: "state",
403
+ key: "minor-mode",
404
+ values: actionId === "activate" ? [...modes, MODE_STATUS_ID] : modes
405
+ });
406
+ modeOwner.publish();
407
+ return { message: actionId === "activate" ? "Loop tools activated." : "Loop tools deactivated. Existing loops are unchanged." };
408
+ }
409
+ }).createOwner(void 0);
410
+ const publish = () => {
411
+ if (disposed) return;
412
+ modeOwner.publish();
413
+ publishView();
414
+ };
415
+ const unsubscribe = launchers.subscribe(publish);
416
+ let submitting = false;
417
+ const pending = /* @__PURE__ */ new Set();
418
+ for (const cron of [false, true]) launchers.register({
419
+ id: cron ? "po.cron" : "po.default",
420
+ source: PACKAGE_SOURCE,
421
+ label: cron ? "Cron loop" : "Default loop",
422
+ description: cron ? "Run a prompt on a five-field cron schedule." : "Run a prompt in this session on an interval.",
423
+ inputSchema: { ...cron ? CronLoopSchema : IntervalLoopSchema },
424
+ async launch(request) {
425
+ const execution = host.context;
426
+ const prepared = prepareLoop(request, cron);
427
+ if (!prepared || request.signal.aborted) return void 0;
428
+ let stopped = false;
429
+ const tick = async (due = true) => {
430
+ if (disposed || stopped || request.signal.aborted) return;
431
+ if (due) pending.add(replay);
432
+ if (submitting || !pending.has(replay)) return;
433
+ submitting = true;
434
+ try {
435
+ const activity = await execution.session.activity();
436
+ if (disposed || stopped || request.signal.aborted || !activity.isIdle || activity.hasPendingMessages) return;
437
+ pending.delete(replay);
438
+ if (!execution.session.admitPrompt) throw new Error("Loop prompt admission is unavailable.");
439
+ await execution.session.admitPrompt(prepared.prompt);
440
+ } catch (error) {
441
+ await execution.client.notify({
442
+ body: `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,
443
+ level: "warning"
444
+ });
445
+ } finally {
446
+ submitting = false;
447
+ }
448
+ };
449
+ const replay = () => tick(false);
450
+ let stopTimer;
451
+ let detail;
452
+ if ("cron" in prepared) {
453
+ const job = new Cron(prepared.cron, {
454
+ timezone: prepared.timezone,
455
+ unref: true
456
+ }, () => tick());
457
+ if (job.nextRun() === null) {
458
+ job.stop();
459
+ throw new Error("Cron expression has no future run.");
460
+ }
461
+ stopTimer = () => {
462
+ job.stop();
463
+ };
464
+ detail = `${prepared.cron} (${prepared.timezone})`;
465
+ } else {
466
+ const timer = setInterval(() => {
467
+ tick();
468
+ }, prepared.intervalSeconds * 1e3);
469
+ timer.unref?.();
470
+ stopTimer = () => clearInterval(timer);
471
+ detail = `every ${prepared.intervalSeconds}s`;
472
+ tick();
473
+ }
474
+ return {
475
+ instanceId: request.instanceId,
476
+ label: cron ? "Cron loop" : "Default loop",
477
+ detail,
478
+ stop() {
479
+ stopped = true;
480
+ pending.delete(replay);
481
+ stopTimer();
482
+ }
483
+ };
484
+ }
485
+ });
486
+ return {
487
+ loopTools: createLoopTools(() => launchers, () => {
488
+ if (!modeSelected()) throw new Error("Enable Loop minor mode before using agent loop tools.");
489
+ }).map((tool) => ({
490
+ ...tool,
491
+ when: {
492
+ state: { "minor-mode": MODE_STATUS_ID },
493
+ attribution: {
494
+ kind: "minor",
495
+ mode: MODE_STATUS_ID
496
+ }
497
+ }
498
+ })),
499
+ services: [(context) => {
500
+ context.plugin((provider) => {
501
+ provider.provide(DOOM_LOOP_LAUNCHERS_SERVICE, launchers);
502
+ });
503
+ context.effect(() => host.subscribeSelection(publish));
504
+ }, serverMinorModes([modeOwner])],
505
+ resources: [{
506
+ when: {
507
+ state: { "minor-mode": MODE_STATUS_ID },
508
+ attribution: {
509
+ kind: "minor",
510
+ mode: MODE_STATUS_ID
511
+ }
512
+ },
513
+ name: "po-use-loop",
514
+ kind: "skill",
515
+ read: () => readPackageResource(import.meta.url, "src/prompts/po-use-loop/SKILL.md")
516
+ }],
517
+ activities: [{
518
+ name: "po-loop",
519
+ async start() {
520
+ publish();
521
+ return async () => {
522
+ await launchers.stopAll("Session loop activity stopped.");
523
+ publish();
524
+ };
525
+ }
526
+ }],
527
+ commands: [{
528
+ name: LIST_COMMAND_NAME,
529
+ description: "List or stop session loops. Usage: /loops [stop instanceId].",
530
+ async execute(args, execution) {
531
+ const parts = args.trim().split(/\s+/u);
532
+ if (parts[0] === "stop" && parts.length === 2) {
533
+ const stopped = await launchers.stop(parts[1], "Stopped manually.");
534
+ await execution.client.notify({
535
+ body: stopped ? "Loop stopped." : "Loop instance was not active.",
536
+ level: "info"
537
+ });
538
+ return;
539
+ }
540
+ if (args.trim()) throw new Error("Usage: /loops [stop instanceId]");
541
+ const instances = launchers.listInstances();
542
+ await execution.client.notify({
543
+ body: instances.length === 0 ? "No loops are active." : JSON.stringify(instances, null, 2),
544
+ level: "info"
545
+ });
546
+ }
547
+ }],
548
+ hooks: [
549
+ {
550
+ event: "agent_settled",
551
+ async handle() {
552
+ if (!disposed) await pending.values().next().value?.();
553
+ }
554
+ },
555
+ {
556
+ event: "session_start",
557
+ async handle() {
558
+ publish();
559
+ }
560
+ },
561
+ {
562
+ event: "session_shutdown",
563
+ async handle() {
564
+ await launchers.stopAll("Headless session shutdown.");
565
+ }
566
+ }
567
+ ],
568
+ onStart: publish,
569
+ async onDispose() {
570
+ if (disposed) return;
571
+ disposed = true;
572
+ pending.clear();
573
+ unsubscribe();
574
+ await launchers.dispose("Headless loop facet disposed.");
575
+ }
576
+ };
577
+ }
578
+ //#endregion
579
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.ts
580
+ var runtime_server_default = (({ agent }) => agent ? createSessionState(agent) : { loopTools: [] });
581
+ //#endregion
582
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
583
+ var root_server_default = defineRoot((context) => {
584
+ const value = runtime_server_default(context);
585
+ return {
586
+ value,
587
+ services: value.services,
588
+ activities: value.activities,
589
+ onStart: value.onStart,
590
+ onStop: value.onStop,
591
+ onDispose: value.onDispose
592
+ };
593
+ });
594
+ //#endregion
595
+ //#region src/extensions/workspaces/sessions/(backend)/command/loops.server.ts
596
+ var loops_server_default = defineRoutedContribution((context) => context.root.commands?.[0], { cardinality: "optional" });
597
+ //#endregion
598
+ //#region src/extensions/workspaces/sessions/(backend)/hook/agent-settled.server.ts
599
+ var agent_settled_server_default = defineRoutedContribution((context) => context.root.hooks?.find((hook) => hook.event === "agent_settled"), { cardinality: "optional" });
600
+ //#endregion
601
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts
602
+ var session_shutdown_server_default = defineRoutedContribution((context) => context.root.hooks?.find((hook) => hook.event === "session_shutdown"), { cardinality: "optional" });
603
+ //#endregion
604
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts
605
+ var session_start_server_default = defineRoutedContribution((context) => context.root.hooks?.find((hook) => hook.event === "session_start"), { cardinality: "optional" });
606
+ //#endregion
607
+ //#region src/extensions/workspaces/sessions/(backend)/resource/po-use-loop.server.ts
608
+ var po_use_loop_server_default = defineRoutedContribution((context) => context.root.resources?.[0], { cardinality: "optional" });
609
+ //#endregion
610
+ //#region src/extensions/workspaces/sessions/(backend)/tool/loop-list.server.ts
611
+ var loop_list_server_default = defineTool$1((context) => context.root.loopTools[0]);
612
+ //#endregion
613
+ //#region src/extensions/workspaces/sessions/(backend)/tool/loop-start.server.ts
614
+ var loop_start_server_default = defineTool$1((context) => context.root.loopTools[1]);
615
+ //#endregion
616
+ //#region src/extensions/workspaces/sessions/(backend)/tool/loop-stop.server.ts
617
+ var loop_stop_server_default = defineTool$1((context) => context.root.loopTools[2]);
618
+ //#endregion
619
+ //#region generated/server.ts
620
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
621
+ /* v8 ignore next -- generated normalization branch */
622
+ const defined = (values) => values.filter((value) => value !== void 0);
623
+ const via = (identity, value) => value === void 0 ? void 0 : {
624
+ ...identity,
625
+ ...value
626
+ };
627
+ const facet = defineServerPlugin({
628
+ name: "@agimon-ai/po-loop",
629
+ providerOverrides: composeServerProviderOverrides(root_server_default),
630
+ session: async (context) => {
631
+ const scopeSession = await root_server_default(context);
632
+ const contextSession = {
633
+ ...context,
634
+ root: scopeSession.value
635
+ };
636
+ return {
637
+ ...composeRootHooks(scopeSession),
638
+ get commands() {
639
+ return defined([via({ name: "loops" }, at(loops_server_default, contextSession))]);
640
+ },
641
+ get hooks() {
642
+ return defined([
643
+ via({ event: "agent_settled" }, at(agent_settled_server_default, contextSession)),
644
+ via({ event: "session_shutdown" }, at(session_shutdown_server_default, contextSession)),
645
+ via({ event: "session_start" }, at(session_start_server_default, contextSession))
646
+ ]);
647
+ },
648
+ get resources() {
649
+ return defined([at(po_use_loop_server_default, contextSession)]);
650
+ },
651
+ get tools() {
652
+ return [
653
+ via({ name: "loop_list" }, at(loop_list_server_default, contextSession)),
654
+ via({ name: "loop_start" }, at(loop_start_server_default, contextSession)),
655
+ via({ name: "loop_stop" }, at(loop_stop_server_default, contextSession))
656
+ ];
657
+ },
658
+ services: [...scopeSession.services ?? []],
659
+ get activities() {
660
+ return [...scopeSession.activities ?? []];
661
+ }
662
+ };
663
+ }
664
+ });
665
+ //#endregion
666
+ export { facet as default, facet };
667
+
668
+ //# sourceMappingURL=server.mjs.map