@undefineds.co/linx 0.3.5 → 0.3.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.
Files changed (172) hide show
  1. package/README.md +58 -23
  2. package/dist/generated/version.js +1 -1
  3. package/dist/generated/version.js.map +1 -1
  4. package/dist/index.js +334 -162
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/account-session.js +4 -8
  7. package/dist/lib/account-session.js.map +1 -1
  8. package/dist/lib/ai-command.js +228 -178
  9. package/dist/lib/ai-command.js.map +1 -1
  10. package/dist/lib/auto-mode/archive.js +38 -7
  11. package/dist/lib/auto-mode/archive.js.map +1 -1
  12. package/dist/lib/auto-mode/auth.js.map +1 -1
  13. package/dist/lib/auto-mode/display.js +71 -45
  14. package/dist/lib/auto-mode/display.js.map +1 -1
  15. package/dist/lib/auto-mode/format.js +9 -7
  16. package/dist/lib/auto-mode/format.js.map +1 -1
  17. package/dist/lib/auto-mode/hooks/claude.js +12 -2
  18. package/dist/lib/auto-mode/hooks/claude.js.map +1 -1
  19. package/dist/lib/auto-mode/hooks/codex.js +17 -7
  20. package/dist/lib/auto-mode/hooks/codex.js.map +1 -1
  21. package/dist/lib/auto-mode/hooks/index.js +28 -8
  22. package/dist/lib/auto-mode/hooks/index.js.map +1 -1
  23. package/dist/lib/auto-mode/pod-ai.js +20 -37
  24. package/dist/lib/auto-mode/pod-ai.js.map +1 -1
  25. package/dist/lib/auto-mode/pod-approval.js +124 -195
  26. package/dist/lib/auto-mode/pod-approval.js.map +1 -1
  27. package/dist/lib/auto-mode/pod-persistence.js +169 -90
  28. package/dist/lib/auto-mode/pod-persistence.js.map +1 -1
  29. package/dist/lib/auto-mode/runner.js +683 -81
  30. package/dist/lib/auto-mode/runner.js.map +1 -1
  31. package/dist/lib/auto-mode/secretary.js +186 -41
  32. package/dist/lib/auto-mode/secretary.js.map +1 -1
  33. package/dist/lib/auto-mode-command.js +32 -32
  34. package/dist/lib/auto-mode-command.js.map +1 -1
  35. package/dist/lib/chat-api.js +242 -50
  36. package/dist/lib/chat-api.js.map +1 -1
  37. package/dist/lib/codex-plugin/bridge.js +164 -17
  38. package/dist/lib/codex-plugin/bridge.js.map +1 -1
  39. package/dist/lib/codex-plugin/codex-native-proxy.js +370 -34
  40. package/dist/lib/codex-plugin/codex-native-proxy.js.map +1 -1
  41. package/dist/lib/credentials-store.js +33 -42
  42. package/dist/lib/credentials-store.js.map +1 -1
  43. package/dist/lib/linx-cloud-errors.js +61 -0
  44. package/dist/lib/linx-cloud-errors.js.map +1 -0
  45. package/dist/lib/linx-tui-contract.js +8 -5
  46. package/dist/lib/linx-tui-contract.js.map +1 -1
  47. package/dist/lib/login-command.js +9 -2
  48. package/dist/lib/login-command.js.map +1 -1
  49. package/dist/lib/models.js +3 -20
  50. package/dist/lib/models.js.map +1 -1
  51. package/dist/lib/oidc-auth.js +143 -17
  52. package/dist/lib/oidc-auth.js.map +1 -1
  53. package/dist/lib/oidc-session-storage.js +2 -6
  54. package/dist/lib/oidc-session-storage.js.map +1 -1
  55. package/dist/lib/pi-adapter/auto-input-controller.js +988 -0
  56. package/dist/lib/pi-adapter/auto-input-controller.js.map +1 -0
  57. package/dist/lib/pi-adapter/backend-command.js +2 -0
  58. package/dist/lib/pi-adapter/backend-command.js.map +1 -0
  59. package/dist/lib/pi-adapter/backend-credentials.js +80 -0
  60. package/dist/lib/pi-adapter/backend-credentials.js.map +1 -0
  61. package/dist/lib/pi-adapter/branding.js +246 -108
  62. package/dist/lib/pi-adapter/branding.js.map +1 -1
  63. package/dist/lib/pi-adapter/control-state.js +72 -0
  64. package/dist/lib/pi-adapter/control-state.js.map +1 -0
  65. package/dist/lib/pi-adapter/interactive.js +2634 -30
  66. package/dist/lib/pi-adapter/interactive.js.map +1 -1
  67. package/dist/lib/pi-adapter/pod-approval.js +382 -210
  68. package/dist/lib/pi-adapter/pod-approval.js.map +1 -1
  69. package/dist/lib/pi-adapter/pod-mirror-mapping.js +71 -17
  70. package/dist/lib/pi-adapter/pod-mirror-mapping.js.map +1 -1
  71. package/dist/lib/pi-adapter/pod-mirror.js +531 -64
  72. package/dist/lib/pi-adapter/pod-mirror.js.map +1 -1
  73. package/dist/lib/pi-adapter/pod-native.js +81 -85
  74. package/dist/lib/pi-adapter/pod-native.js.map +1 -1
  75. package/dist/lib/pi-adapter/pod-status-output.js +54 -0
  76. package/dist/lib/pi-adapter/pod-status-output.js.map +1 -0
  77. package/dist/lib/pi-adapter/runtime.js +458 -228
  78. package/dist/lib/pi-adapter/runtime.js.map +1 -1
  79. package/dist/lib/pi-adapter/session-control.js +509 -0
  80. package/dist/lib/pi-adapter/session-control.js.map +1 -0
  81. package/dist/lib/pi-adapter/session.js +35 -22
  82. package/dist/lib/pi-adapter/session.js.map +1 -1
  83. package/dist/lib/pi-adapter/stream.js +89 -32
  84. package/dist/lib/pi-adapter/stream.js.map +1 -1
  85. package/dist/lib/pi-adapter/sync-recovery.js +89 -0
  86. package/dist/lib/pi-adapter/sync-recovery.js.map +1 -0
  87. package/dist/lib/pi-adapter/web-fetch.js +13 -14
  88. package/dist/lib/pi-adapter/web-fetch.js.map +1 -1
  89. package/dist/lib/pod-chat-store.js +254 -78
  90. package/dist/lib/pod-chat-store.js.map +1 -1
  91. package/dist/lib/pod-data-session.js +156 -35
  92. package/dist/lib/pod-data-session.js.map +1 -1
  93. package/dist/lib/solid-auth-store.js +27 -0
  94. package/dist/lib/solid-auth-store.js.map +1 -0
  95. package/dist/lib/solid-auth.js +2 -4
  96. package/dist/lib/solid-auth.js.map +1 -1
  97. package/dist/lib/solid-client-credentials-login.js +100 -0
  98. package/dist/lib/solid-client-credentials-login.js.map +1 -0
  99. package/dist/lib/solid-local-store.js +31 -0
  100. package/dist/lib/solid-local-store.js.map +1 -0
  101. package/dist/lib/symphony/archive.js +328 -18
  102. package/dist/lib/symphony/archive.js.map +1 -1
  103. package/dist/lib/symphony/pod-projection.js +2222 -0
  104. package/dist/lib/symphony/pod-projection.js.map +1 -0
  105. package/dist/lib/symphony-command.js +602 -178
  106. package/dist/lib/symphony-command.js.map +1 -1
  107. package/dist/lib/sync-checkpoint-store.js +74 -0
  108. package/dist/lib/sync-checkpoint-store.js.map +1 -0
  109. package/dist/skills/symphony/SKILL.md +665 -0
  110. package/package.json +15 -9
  111. package/vendor/agent-runtime/dist/agent-runtime.d.ts +137 -0
  112. package/vendor/agent-runtime/dist/agent-runtime.js +211 -0
  113. package/vendor/agent-runtime/dist/auto-mode.d.ts +78 -13
  114. package/vendor/agent-runtime/dist/auto-mode.js +288 -31
  115. package/vendor/agent-runtime/dist/control-plane.d.ts +28 -0
  116. package/vendor/agent-runtime/dist/control-plane.js +79 -0
  117. package/vendor/agent-runtime/dist/file-sync.d.ts +157 -0
  118. package/vendor/agent-runtime/dist/file-sync.js +314 -0
  119. package/vendor/agent-runtime/dist/index.d.ts +7 -0
  120. package/vendor/agent-runtime/dist/index.js +7 -0
  121. package/vendor/agent-runtime/dist/reconciler.d.ts +117 -0
  122. package/vendor/agent-runtime/dist/reconciler.js +361 -0
  123. package/vendor/agent-runtime/dist/symphony.d.ts +128 -8
  124. package/vendor/agent-runtime/dist/symphony.js +362 -57
  125. package/vendor/agent-runtime/dist/sync.d.ts +271 -0
  126. package/vendor/agent-runtime/dist/sync.js +550 -0
  127. package/vendor/agent-runtime/dist/thread-reconciler-controller.d.ts +58 -0
  128. package/vendor/agent-runtime/dist/thread-reconciler-controller.js +137 -0
  129. package/vendor/agent-runtime/dist/turn-controller.js +2 -2
  130. package/vendor/agent-runtime/dist/wake-scheduler.d.ts +67 -0
  131. package/vendor/agent-runtime/dist/wake-scheduler.js +194 -0
  132. package/vendor/agent-runtime/package.json +8 -1
  133. package/vendor/pi-web-access/CHANGELOG.md +387 -0
  134. package/vendor/pi-web-access/LICENSE +21 -0
  135. package/vendor/pi-web-access/README.md +352 -0
  136. package/vendor/pi-web-access/activity.ts +101 -0
  137. package/vendor/pi-web-access/banner.png +0 -0
  138. package/vendor/pi-web-access/chrome-cookies.ts +322 -0
  139. package/vendor/pi-web-access/code-search.ts +107 -0
  140. package/vendor/pi-web-access/curator-page.ts +3359 -0
  141. package/vendor/pi-web-access/curator-server.ts +605 -0
  142. package/vendor/pi-web-access/exa.ts +520 -0
  143. package/vendor/pi-web-access/extract.ts +641 -0
  144. package/vendor/pi-web-access/gemini-api.ts +112 -0
  145. package/vendor/pi-web-access/gemini-search.ts +361 -0
  146. package/vendor/pi-web-access/gemini-url-context.ts +126 -0
  147. package/vendor/pi-web-access/gemini-web-config.ts +52 -0
  148. package/vendor/pi-web-access/gemini-web.ts +396 -0
  149. package/vendor/pi-web-access/github-api.ts +196 -0
  150. package/vendor/pi-web-access/github-extract.ts +634 -0
  151. package/vendor/pi-web-access/index.ts +2346 -0
  152. package/vendor/pi-web-access/package.json +45 -0
  153. package/vendor/pi-web-access/pdf-extract.ts +192 -0
  154. package/vendor/pi-web-access/perplexity.ts +195 -0
  155. package/vendor/pi-web-access/pi-web-fetch-demo.mp4 +0 -0
  156. package/vendor/pi-web-access/rsc-extract.ts +338 -0
  157. package/vendor/pi-web-access/skills/librarian/SKILL.md +195 -0
  158. package/vendor/pi-web-access/storage.ts +72 -0
  159. package/vendor/pi-web-access/summary-review.ts +276 -0
  160. package/vendor/pi-web-access/test/gemini-web-cookie-opt-in.test.mjs +41 -0
  161. package/vendor/pi-web-access/test/pdf-extract.test.mjs +95 -0
  162. package/vendor/pi-web-access/utils.ts +44 -0
  163. package/vendor/pi-web-access/video-extract.ts +378 -0
  164. package/vendor/pi-web-access/youtube-extract.ts +310 -0
  165. package/dist/lib/pi-adapter/auth.js +0 -68
  166. package/dist/lib/pi-adapter/auth.js.map +0 -1
  167. package/dist/lib/pi-adapter/pod-tools.js +0 -140
  168. package/dist/lib/pi-adapter/pod-tools.js.map +0 -1
  169. package/dist/skills/drizzle-solid/SKILL.md +0 -340
  170. package/dist/skills/pod-storage/SKILL.md +0 -100
  171. package/dist/skills/solid-modeling/SKILL.md +0 -274
  172. package/dist/skills/xpod-componentsjs/SKILL.md +0 -284
@@ -0,0 +1,137 @@
1
+ import { reconcileThreadEvent, summarizeReconcileDecision, } from './reconciler.js';
2
+ import { createWakeJobScheduler, defaultWakeJobDedupeKey, summarizeWakeJobExecutionRecord, summarizeWakeJobSchedulerSnapshot, } from './wake-scheduler.js';
3
+ export function createThreadReconcilerController(options) {
4
+ return new ConfiguredThreadReconcilerController(options);
5
+ }
6
+ export function decideThreadControlEvent(input) {
7
+ const decision = reconcileThreadEvent(input);
8
+ return {
9
+ decision,
10
+ summary: summarizeReconcileDecision(decision),
11
+ };
12
+ }
13
+ export async function runThreadReconcilerCycle(options) {
14
+ const { event, dispatchOptions, onDispatched, ...controllerOptions } = options;
15
+ const controller = createThreadReconcilerController({
16
+ ...controllerOptions,
17
+ autoStart: false,
18
+ });
19
+ const dispatch = controller.dispatch(event, dispatchOptions);
20
+ await onDispatched?.(dispatch);
21
+ const drain = await controller.startAndDrain();
22
+ return {
23
+ ...dispatch,
24
+ ...drain,
25
+ };
26
+ }
27
+ class ConfiguredThreadReconcilerController {
28
+ options;
29
+ scheduler;
30
+ contexts = new Map();
31
+ constructor(options) {
32
+ this.options = options;
33
+ this.scheduler = createWakeJobScheduler({
34
+ concurrency: options.concurrency,
35
+ now: options.now,
36
+ dedupeKey: defaultWakeJobDedupeKey,
37
+ handler: async (job, record) => {
38
+ const context = this.contexts.get(record.key);
39
+ if (!context) {
40
+ throw new Error(`No reconciler decision found for wake job ${record.key}`);
41
+ }
42
+ return options.handleWakeJob({
43
+ job,
44
+ record,
45
+ decision: context.decision,
46
+ decisionSummary: context.summary,
47
+ });
48
+ },
49
+ onQueued: (record) => this.emitWakeHook('queued', record),
50
+ onStarted: (record) => this.emitWakeHook('started', record),
51
+ onCompleted: (record) => this.emitWakeHook('completed', record),
52
+ onFailed: (record) => this.emitWakeHook('failed', record),
53
+ });
54
+ if (options.autoStart !== false) {
55
+ this.scheduler.start();
56
+ }
57
+ }
58
+ dispatch(event, options = {}) {
59
+ const { decision, summary } = decideThreadControlEvent({
60
+ ...options,
61
+ policy: this.options.policy,
62
+ event,
63
+ });
64
+ this.options.onDecision?.(summary);
65
+ for (const job of decision.wakeJobs) {
66
+ const key = defaultWakeJobDedupeKey(job);
67
+ if (!this.contexts.has(key)) {
68
+ this.contexts.set(key, {
69
+ decision,
70
+ summary,
71
+ });
72
+ }
73
+ }
74
+ const wakeRecords = this.scheduler.submit(decision.wakeJobs);
75
+ for (const record of wakeRecords) {
76
+ if (!this.contexts.has(record.key)) {
77
+ this.contexts.set(record.key, {
78
+ decision,
79
+ summary,
80
+ });
81
+ }
82
+ }
83
+ return {
84
+ decision,
85
+ summary,
86
+ wakeRecords,
87
+ wakeRecordSummaries: wakeRecords.map(summarizeWakeJobExecutionRecord),
88
+ };
89
+ }
90
+ async dispatchAndDrain(event, options = {}) {
91
+ const dispatch = this.dispatch(event, options);
92
+ const drain = await this.startAndDrain();
93
+ return {
94
+ ...dispatch,
95
+ ...drain,
96
+ };
97
+ }
98
+ async startAndDrain() {
99
+ this.start();
100
+ await this.drain();
101
+ const scheduler = this.snapshot();
102
+ return {
103
+ scheduler,
104
+ schedulerSummary: summarizeWakeJobSchedulerSnapshot(scheduler),
105
+ };
106
+ }
107
+ start() {
108
+ this.scheduler.start();
109
+ }
110
+ stop() {
111
+ this.scheduler.stop();
112
+ }
113
+ drain() {
114
+ return this.scheduler.drain();
115
+ }
116
+ snapshot() {
117
+ return this.scheduler.snapshot();
118
+ }
119
+ emitWakeHook(status, record) {
120
+ const context = this.contexts.get(record.key);
121
+ if (!context) {
122
+ return;
123
+ }
124
+ if (status === 'queued') {
125
+ this.options.onWakeJobQueued?.(record, context.summary);
126
+ }
127
+ else if (status === 'started') {
128
+ this.options.onWakeJobStarted?.(record, context.summary);
129
+ }
130
+ else if (status === 'completed') {
131
+ this.options.onWakeJobCompleted?.(record, context.summary);
132
+ }
133
+ else {
134
+ this.options.onWakeJobFailed?.(record, context.summary);
135
+ }
136
+ }
137
+ }
@@ -90,7 +90,7 @@ export const GROUP_AGENT_TURN_RULE = {
90
90
  export const AUTO_MODE_SECRETARY_APPROVAL_RULE = {
91
91
  id: 'auto-mode.secretary.approval',
92
92
  trigger: 'approval.required',
93
- targetAgent: 'ai-secretary',
93
+ targetAgent: '__secretary__',
94
94
  targetRole: 'secretary',
95
95
  requiredCapabilities: ['approval.request', 'approval.options'],
96
96
  context: {
@@ -108,7 +108,7 @@ export const AUTO_MODE_SECRETARY_APPROVAL_RULE = {
108
108
  export const AUTO_MODE_SECRETARY_INPUT_RULE = {
109
109
  id: 'auto-mode.secretary.input',
110
110
  trigger: 'input.required',
111
- targetAgent: 'ai-secretary',
111
+ targetAgent: '__secretary__',
112
112
  targetRole: 'secretary',
113
113
  requiredCapabilities: ['input.structured'],
114
114
  context: {
@@ -0,0 +1,67 @@
1
+ import type { WakeJob, WakeJobPriority } from './reconciler.js';
2
+ type MaybePromise<T> = T | Promise<T>;
3
+ export type WakeJobExecutionStatus = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled' | 'skipped';
4
+ export interface WakeJobExecutionRecord {
5
+ key: string;
6
+ job: WakeJob;
7
+ status: WakeJobExecutionStatus;
8
+ queuedAt: string;
9
+ startedAt?: string;
10
+ completedAt?: string;
11
+ error?: string;
12
+ result?: unknown;
13
+ }
14
+ export type WakeJobHandler = (job: WakeJob, record: WakeJobExecutionRecord) => MaybePromise<unknown>;
15
+ export interface WakeJobSchedulerOptions {
16
+ handler: WakeJobHandler;
17
+ concurrency?: number;
18
+ now?: () => Date;
19
+ dedupeKey?: (job: WakeJob) => string;
20
+ onQueued?: (record: WakeJobExecutionRecord) => void;
21
+ onStarted?: (record: WakeJobExecutionRecord) => void;
22
+ onCompleted?: (record: WakeJobExecutionRecord) => void;
23
+ onFailed?: (record: WakeJobExecutionRecord) => void;
24
+ }
25
+ export interface WakeJobSchedulerSnapshot {
26
+ queued: WakeJobExecutionRecord[];
27
+ running: WakeJobExecutionRecord[];
28
+ completed: WakeJobExecutionRecord[];
29
+ failed: WakeJobExecutionRecord[];
30
+ cancelled: WakeJobExecutionRecord[];
31
+ skipped: WakeJobExecutionRecord[];
32
+ all: WakeJobExecutionRecord[];
33
+ }
34
+ export interface WakeJobExecutionRecordSummary {
35
+ key: string;
36
+ status: WakeJobExecutionStatus;
37
+ targetAgent: string;
38
+ targetRole: string;
39
+ trigger: string;
40
+ priority: WakeJobPriority;
41
+ queuedAt: string;
42
+ startedAt?: string;
43
+ completedAt?: string;
44
+ error?: string;
45
+ result?: unknown;
46
+ }
47
+ export interface WakeJobSchedulerSnapshotSummary {
48
+ queued: WakeJobExecutionRecordSummary[];
49
+ running: WakeJobExecutionRecordSummary[];
50
+ completed: WakeJobExecutionRecordSummary[];
51
+ failed: WakeJobExecutionRecordSummary[];
52
+ cancelled: WakeJobExecutionRecordSummary[];
53
+ skipped: WakeJobExecutionRecordSummary[];
54
+ }
55
+ export interface WakeJobScheduler {
56
+ submit(job: WakeJob | WakeJob[]): WakeJobExecutionRecord[];
57
+ start(): void;
58
+ stop(): void;
59
+ drain(): Promise<void>;
60
+ snapshot(): WakeJobSchedulerSnapshot;
61
+ get(key: string): WakeJobExecutionRecord | undefined;
62
+ }
63
+ export declare function createWakeJobScheduler(options: WakeJobSchedulerOptions): WakeJobScheduler;
64
+ export declare function defaultWakeJobDedupeKey(job: WakeJob): string;
65
+ export declare function summarizeWakeJobExecutionRecord(record: WakeJobExecutionRecord): WakeJobExecutionRecordSummary;
66
+ export declare function summarizeWakeJobSchedulerSnapshot(snapshot: WakeJobSchedulerSnapshot): WakeJobSchedulerSnapshotSummary;
67
+ export {};
@@ -0,0 +1,194 @@
1
+ const PRIORITY_RANK = {
2
+ high: 3,
3
+ normal: 2,
4
+ low: 1,
5
+ };
6
+ export function createWakeJobScheduler(options) {
7
+ return new InMemoryWakeJobScheduler(options);
8
+ }
9
+ export function defaultWakeJobDedupeKey(job) {
10
+ const source = job.sourceEventId ?? job.id ?? job.sourceEventType;
11
+ return [
12
+ job.thread,
13
+ job.chat ?? '',
14
+ job.targetAgent,
15
+ job.targetRole,
16
+ source,
17
+ job.trigger,
18
+ ].join('|');
19
+ }
20
+ export function summarizeWakeJobExecutionRecord(record) {
21
+ return {
22
+ key: record.key,
23
+ status: record.status,
24
+ targetAgent: record.job.targetAgent,
25
+ targetRole: record.job.targetRole,
26
+ trigger: record.job.trigger,
27
+ priority: record.job.priority,
28
+ queuedAt: record.queuedAt,
29
+ startedAt: record.startedAt,
30
+ completedAt: record.completedAt,
31
+ error: record.error,
32
+ result: record.result,
33
+ };
34
+ }
35
+ export function summarizeWakeJobSchedulerSnapshot(snapshot) {
36
+ return {
37
+ queued: snapshot.queued.map(summarizeWakeJobExecutionRecord),
38
+ running: snapshot.running.map(summarizeWakeJobExecutionRecord),
39
+ completed: snapshot.completed.map(summarizeWakeJobExecutionRecord),
40
+ failed: snapshot.failed.map(summarizeWakeJobExecutionRecord),
41
+ cancelled: snapshot.cancelled.map(summarizeWakeJobExecutionRecord),
42
+ skipped: snapshot.skipped.map(summarizeWakeJobExecutionRecord),
43
+ };
44
+ }
45
+ class InMemoryWakeJobScheduler {
46
+ options;
47
+ handler;
48
+ concurrency;
49
+ now;
50
+ dedupeKey;
51
+ records = new Map();
52
+ queue = [];
53
+ running = new Set();
54
+ drainResolvers = [];
55
+ started = false;
56
+ sequence = 0;
57
+ constructor(options) {
58
+ this.options = options;
59
+ this.handler = options.handler;
60
+ this.concurrency = normalizeConcurrency(options.concurrency);
61
+ this.now = options.now ?? (() => new Date());
62
+ this.dedupeKey = options.dedupeKey ?? defaultWakeJobDedupeKey;
63
+ }
64
+ submit(input) {
65
+ const jobs = Array.isArray(input) ? input : [input];
66
+ const records = jobs.map((job) => this.enqueue(job));
67
+ this.pump();
68
+ return records.map(cloneRecord);
69
+ }
70
+ start() {
71
+ this.started = true;
72
+ this.pump();
73
+ }
74
+ stop() {
75
+ this.started = false;
76
+ }
77
+ drain() {
78
+ if (this.isDrained()) {
79
+ return Promise.resolve();
80
+ }
81
+ return new Promise((resolve) => {
82
+ this.drainResolvers.push(resolve);
83
+ this.pump();
84
+ });
85
+ }
86
+ snapshot() {
87
+ const all = [...this.records.values()].map(cloneRecord);
88
+ return {
89
+ queued: all.filter((record) => record.status === 'queued'),
90
+ running: all.filter((record) => record.status === 'running'),
91
+ completed: all.filter((record) => record.status === 'completed'),
92
+ failed: all.filter((record) => record.status === 'failed'),
93
+ cancelled: all.filter((record) => record.status === 'cancelled'),
94
+ skipped: all.filter((record) => record.status === 'skipped'),
95
+ all,
96
+ };
97
+ }
98
+ get(key) {
99
+ const record = this.records.get(key);
100
+ return record ? cloneRecord(record) : undefined;
101
+ }
102
+ enqueue(job) {
103
+ const key = this.dedupeKey(job);
104
+ const existing = this.records.get(key);
105
+ if (existing) {
106
+ return existing;
107
+ }
108
+ const record = {
109
+ key,
110
+ job,
111
+ status: 'queued',
112
+ queuedAt: this.now().toISOString(),
113
+ };
114
+ this.records.set(key, record);
115
+ this.sequence += 1;
116
+ this.queue.push({
117
+ record,
118
+ sequence: this.sequence,
119
+ });
120
+ this.options.onQueued?.(cloneRecord(record));
121
+ return record;
122
+ }
123
+ pump() {
124
+ while (this.started && this.running.size < this.concurrency && this.queue.length > 0) {
125
+ const queued = this.takeNextQueued();
126
+ this.startRecord(queued.record);
127
+ }
128
+ this.resolveDrainIfIdle();
129
+ }
130
+ takeNextQueued() {
131
+ let bestIndex = 0;
132
+ for (let index = 1; index < this.queue.length; index += 1) {
133
+ if (compareQueuedJobs(this.queue[index], this.queue[bestIndex]) < 0) {
134
+ bestIndex = index;
135
+ }
136
+ }
137
+ const [queued] = this.queue.splice(bestIndex, 1);
138
+ return queued;
139
+ }
140
+ startRecord(record) {
141
+ record.status = 'running';
142
+ record.startedAt = this.now().toISOString();
143
+ this.running.add(record.key);
144
+ this.options.onStarted?.(cloneRecord(record));
145
+ void Promise.resolve()
146
+ .then(() => this.handler(record.job, cloneRecord(record)))
147
+ .then((result) => {
148
+ record.status = 'completed';
149
+ record.completedAt = this.now().toISOString();
150
+ record.result = result;
151
+ this.options.onCompleted?.(cloneRecord(record));
152
+ })
153
+ .catch((cause) => {
154
+ const error = cause instanceof Error ? cause.message : String(cause);
155
+ record.status = 'failed';
156
+ record.completedAt = this.now().toISOString();
157
+ record.error = error;
158
+ this.options.onFailed?.(cloneRecord(record));
159
+ })
160
+ .finally(() => {
161
+ this.running.delete(record.key);
162
+ this.pump();
163
+ });
164
+ }
165
+ isDrained() {
166
+ return this.queue.length === 0 && this.running.size === 0;
167
+ }
168
+ resolveDrainIfIdle() {
169
+ if (!this.isDrained()) {
170
+ return;
171
+ }
172
+ while (this.drainResolvers.length > 0) {
173
+ this.drainResolvers.shift()?.();
174
+ }
175
+ }
176
+ }
177
+ function compareQueuedJobs(left, right) {
178
+ const priority = PRIORITY_RANK[right.record.job.priority] - PRIORITY_RANK[left.record.job.priority];
179
+ return priority === 0 ? left.sequence - right.sequence : priority;
180
+ }
181
+ function normalizeConcurrency(value) {
182
+ if (value === undefined || !Number.isFinite(value)) {
183
+ return 1;
184
+ }
185
+ return Math.max(1, Math.floor(value));
186
+ }
187
+ function cloneRecord(record) {
188
+ return {
189
+ ...record,
190
+ job: {
191
+ ...record.job,
192
+ },
193
+ };
194
+ }
@@ -7,7 +7,14 @@
7
7
  "./acp": "./dist/acp.js",
8
8
  "./auto-mode": "./dist/auto-mode.js",
9
9
  "./companion-model": "./dist/companion-model.js",
10
+ "./control-plane": "./dist/control-plane.js",
11
+ "./file-sync": "./dist/file-sync.js",
12
+ "./reconciler": "./dist/reconciler.js",
10
13
  "./runtime": "./dist/runtime.js",
11
- "./turn-controller": "./dist/turn-controller.js"
14
+ "./symphony": "./dist/symphony.js",
15
+ "./sync": "./dist/sync.js",
16
+ "./thread-reconciler-controller": "./dist/thread-reconciler-controller.js",
17
+ "./turn-controller": "./dist/turn-controller.js",
18
+ "./wake-scheduler": "./dist/wake-scheduler.js"
12
19
  }
13
20
  }