@undefineds.co/linx 0.3.19 → 0.3.20
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/dist/lib/auto-mode/pod-persistence.js +0 -2
- package/dist/lib/auto-mode/pod-persistence.js.map +1 -1
- package/dist/lib/capture/persistence.js +377 -0
- package/dist/lib/capture/persistence.js.map +1 -0
- package/dist/lib/capture/tool.js +242 -0
- package/dist/lib/capture/tool.js.map +1 -0
- package/dist/lib/linx-cloud-errors.js +5 -0
- package/dist/lib/linx-cloud-errors.js.map +1 -1
- package/dist/lib/linx-status-line.js +8 -1
- package/dist/lib/linx-status-line.js.map +1 -1
- package/dist/lib/pi-adapter/branding.js +103 -34
- package/dist/lib/pi-adapter/branding.js.map +1 -1
- package/dist/lib/pi-adapter/interactive.js +32 -23
- package/dist/lib/pi-adapter/interactive.js.map +1 -1
- package/dist/lib/pi-adapter/pod-mirror.js +102 -4
- package/dist/lib/pi-adapter/pod-mirror.js.map +1 -1
- package/dist/lib/pi-adapter/pod-native.js +0 -2
- package/dist/lib/pi-adapter/pod-native.js.map +1 -1
- package/dist/lib/pi-adapter/runtime.js +12 -2
- package/dist/lib/pi-adapter/runtime.js.map +1 -1
- package/dist/lib/status-line-command.js +2 -2
- package/dist/lib/status-line-command.js.map +1 -1
- package/dist/lib/symphony/pod-projection.js +4 -6
- package/dist/lib/symphony/pod-projection.js.map +1 -1
- package/dist/lib/symphony-command.js +1 -1
- package/dist/lib/symphony-command.js.map +1 -1
- package/dist/skills/basic/SKILL.md +46 -0
- package/dist/skills/capture/SKILL.md +165 -0
- package/dist/skills/symphony/SKILL.md +8 -4
- package/dist/skills/xpod-cli/SKILL.md +13 -2
- package/package.json +2 -2
- package/vendor/agent-runtime/dist/coordination.d.ts +93 -0
- package/vendor/agent-runtime/dist/coordination.js +145 -0
- package/vendor/agent-runtime/dist/index.d.ts +1 -0
- package/vendor/agent-runtime/dist/index.js +1 -0
- package/vendor/agent-runtime/dist/reconciler.d.ts +11 -0
- package/vendor/agent-runtime/dist/reconciler.js +41 -3
- package/vendor/agent-runtime/dist/symphony.d.ts +9 -9
- package/vendor/agent-runtime/dist/symphony.js +4 -4
|
@@ -4,6 +4,7 @@ export * from './auto-mode.js';
|
|
|
4
4
|
export * from './companion-model.js';
|
|
5
5
|
export * from './client-inbox-subscription.js';
|
|
6
6
|
export * from './control-plane.js';
|
|
7
|
+
export * from './coordination.js';
|
|
7
8
|
export * from './file-sync.js';
|
|
8
9
|
export * from './reconciler.js';
|
|
9
10
|
export * from './runtime.js';
|
|
@@ -4,6 +4,7 @@ export * from './auto-mode.js';
|
|
|
4
4
|
export * from './companion-model.js';
|
|
5
5
|
export * from './client-inbox-subscription.js';
|
|
6
6
|
export * from './control-plane.js';
|
|
7
|
+
export * from './coordination.js';
|
|
7
8
|
export * from './file-sync.js';
|
|
8
9
|
export * from './reconciler.js';
|
|
9
10
|
export * from './runtime.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentParticipantRole } from './turn-controller.js';
|
|
2
|
+
import { type ClientReconcilerLease, type ReconcilerOwner } from './coordination.js';
|
|
2
3
|
export type ThreadPolicyKind = 'direct' | 'auto' | 'symphony' | 'open_group' | 'review';
|
|
3
4
|
export type ThreadKind = 'main' | 'control' | 'worker' | 'review' | 'schedule' | 'schedule_run';
|
|
4
5
|
export type ReconcilerEventType = 'message.appended' | 'input.required' | 'approval.required' | 'inbox.notification.created' | 'inbox.notification.updated' | 'delivery.submitted' | 'delivery.completed' | 'delivery.failed' | 'schedule.tick' | 'worker.blocked' | 'change.requested' | 'issue.updated' | 'task.updated' | 'run.updated' | (string & {});
|
|
@@ -62,6 +63,9 @@ export interface ThreadControlEvent<TData extends Record<string, unknown> = Reco
|
|
|
62
63
|
}
|
|
63
64
|
export interface ThreadPolicy {
|
|
64
65
|
kind: ThreadPolicyKind;
|
|
66
|
+
reconcilerOwner?: ReconcilerOwner;
|
|
67
|
+
humanAuthorities?: string[];
|
|
68
|
+
humanAuthorityCount?: number;
|
|
65
69
|
secretaryAgent?: string;
|
|
66
70
|
defaultAssistantAgent?: string;
|
|
67
71
|
assignedWorkerAgent?: string;
|
|
@@ -114,6 +118,7 @@ export interface ReconcilerNotificationEvent {
|
|
|
114
118
|
export interface ReconcileDecision {
|
|
115
119
|
id: string;
|
|
116
120
|
policyKind: ThreadPolicyKind;
|
|
121
|
+
reconcilerOwner: ReconcilerOwner;
|
|
117
122
|
event: ThreadControlEvent;
|
|
118
123
|
placement: ThreadPlacement;
|
|
119
124
|
wakeJobs: WakeJob[];
|
|
@@ -140,6 +145,7 @@ export interface WakeJobSummary {
|
|
|
140
145
|
export interface ReconcileDecisionSummary {
|
|
141
146
|
id: string;
|
|
142
147
|
policyKind: ThreadPolicyKind;
|
|
148
|
+
reconcilerOwner: ReconcilerOwner;
|
|
143
149
|
eventType: ReconcilerEventType;
|
|
144
150
|
thread: string;
|
|
145
151
|
chat?: string;
|
|
@@ -151,6 +157,11 @@ export interface ReconcileDecisionSummary {
|
|
|
151
157
|
export interface ReconcileThreadEventInput {
|
|
152
158
|
policy: ThreadPolicyKind | ThreadPolicy;
|
|
153
159
|
event: ThreadControlEvent;
|
|
160
|
+
reconcilerOwner?: ReconcilerOwner;
|
|
161
|
+
humanAuthorities?: string[];
|
|
162
|
+
humanAuthorityCount?: number;
|
|
163
|
+
clientReconcilerLease?: ClientReconcilerLease | null;
|
|
164
|
+
requireClientReconcilerLease?: boolean;
|
|
154
165
|
chat?: string;
|
|
155
166
|
thread?: string;
|
|
156
167
|
now?: Date;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canClientCoordinateThread, resolveReconcilerOwnership, } from './coordination.js';
|
|
1
2
|
const DEFAULT_SECRETARY_AGENT = '__secretary__';
|
|
2
3
|
const DEFAULT_ASSISTANT_AGENT = 'primary-agent';
|
|
3
4
|
const DEFAULT_REVIEWER_AGENT = 'ai-reviewer';
|
|
@@ -24,12 +25,27 @@ export function reconcileThreadEvent(input) {
|
|
|
24
25
|
thread: input.thread,
|
|
25
26
|
randomId: input.randomId,
|
|
26
27
|
});
|
|
27
|
-
const
|
|
28
|
+
const ownership = resolveReconcilerOwnership({
|
|
29
|
+
policyKind: policy.kind,
|
|
30
|
+
humanAuthorities: input.humanAuthorities ?? policy.humanAuthorities,
|
|
31
|
+
humanAuthorityCount: input.humanAuthorityCount ?? policy.humanAuthorityCount,
|
|
32
|
+
reconcilerOwner: input.reconcilerOwner ?? policy.reconcilerOwner,
|
|
33
|
+
});
|
|
34
|
+
const clientCoordinationSkip = resolveClientCoordinationSkip({
|
|
35
|
+
ownership,
|
|
36
|
+
input,
|
|
37
|
+
placement,
|
|
38
|
+
createdAt,
|
|
39
|
+
});
|
|
40
|
+
const jobs = clientCoordinationSkip
|
|
41
|
+
? []
|
|
42
|
+
: selectWakeJobs(policy, event, placement, createdAt, input.randomId, input.client);
|
|
28
43
|
const notificationEvents = selectNotificationEvents(event, placement, createdAt, input.randomId);
|
|
29
|
-
const skippedReason = jobs.length === 0 ? skipReasonFor(policy, event, input.client) : undefined;
|
|
44
|
+
const skippedReason = clientCoordinationSkip ?? (jobs.length === 0 ? skipReasonFor(policy, event, input.client) : undefined);
|
|
30
45
|
return {
|
|
31
46
|
id: createReconcilerId('decision', input.randomId),
|
|
32
47
|
policyKind: policy.kind,
|
|
48
|
+
reconcilerOwner: ownership.reconcilerOwner,
|
|
33
49
|
event,
|
|
34
50
|
placement,
|
|
35
51
|
wakeJobs: jobs,
|
|
@@ -42,6 +58,7 @@ export function summarizeReconcileDecision(decision) {
|
|
|
42
58
|
return {
|
|
43
59
|
id: decision.id,
|
|
44
60
|
policyKind: decision.policyKind,
|
|
61
|
+
reconcilerOwner: decision.reconcilerOwner,
|
|
45
62
|
eventType: decision.event.type,
|
|
46
63
|
thread: decision.placement.thread,
|
|
47
64
|
...(decision.placement.chat ? { chat: decision.placement.chat } : {}),
|
|
@@ -120,6 +137,27 @@ export function resolveThreadPlacement(input) {
|
|
|
120
137
|
kind: 'control',
|
|
121
138
|
};
|
|
122
139
|
}
|
|
140
|
+
function resolveClientCoordinationSkip(input) {
|
|
141
|
+
if (input.ownership.reconcilerOwner !== 'client') {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
if (!input.input.requireClientReconcilerLease && !input.input.clientReconcilerLease) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
const clientId = input.input.client?.id;
|
|
148
|
+
if (canClientCoordinateThread({
|
|
149
|
+
clientId,
|
|
150
|
+
thread: input.placement.thread,
|
|
151
|
+
lease: input.input.clientReconcilerLease,
|
|
152
|
+
now: input.createdAt,
|
|
153
|
+
})) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
const owner = input.input.clientReconcilerLease?.ownerClientId;
|
|
157
|
+
return owner
|
|
158
|
+
? `Client-owned Reconciler is leased by ${owner}; client ${clientId ?? 'unknown'} must not reconcile ${input.placement.thread}.`
|
|
159
|
+
: `Client-owned Reconciler requires an active client coordinator lease for ${input.placement.thread}.`;
|
|
160
|
+
}
|
|
123
161
|
function selectWakeJobs(policy, event, placement, createdAt, randomId, client) {
|
|
124
162
|
if (policy.kind === 'direct') {
|
|
125
163
|
return isUserMessage(event)
|
|
@@ -127,7 +165,7 @@ function selectWakeJobs(policy, event, placement, createdAt, randomId, client) {
|
|
|
127
165
|
targetAgent: policy.defaultAssistantAgent ?? DEFAULT_ASSISTANT_AGENT,
|
|
128
166
|
targetRole: 'primary-agent',
|
|
129
167
|
priority: 'normal',
|
|
130
|
-
reason: '
|
|
168
|
+
reason: 'Single-human assistant surfaces route user messages to the default assistant.',
|
|
131
169
|
createdAt,
|
|
132
170
|
randomId,
|
|
133
171
|
})]
|
|
@@ -11,7 +11,7 @@ export declare const SYMPHONY_ISSUE_FILE_NAME = "issue.json";
|
|
|
11
11
|
export declare const SYMPHONY_TASK_FILE_NAME = "task.json";
|
|
12
12
|
export declare const SYMPHONY_DELIVERY_FILE_NAME = "delivery.json";
|
|
13
13
|
export declare const SYMPHONY_SESSION_FILE_NAME = "session.json";
|
|
14
|
-
export type
|
|
14
|
+
export type WorkerWorkspaceKind = 'git' | 'folder';
|
|
15
15
|
export type SymphonyIdeaStatus = 'captured' | 'exploring' | 'candidate' | 'promoted' | 'deferred' | 'rejected' | 'superseded';
|
|
16
16
|
export type SymphonyIdeaCommitment = 'thought' | 'direction' | 'tentative_decision' | 'committed';
|
|
17
17
|
export type SymphonyIssueStatus = 'open' | 'triaging' | 'in_progress' | 'blocked' | 'resolved' | 'closed';
|
|
@@ -23,13 +23,13 @@ export type SymphonyResourceKind = 'idea' | 'issue' | 'task' | 'delivery' | 'ses
|
|
|
23
23
|
export interface SymphonyReconcilerState {
|
|
24
24
|
decisions: ReconcileDecisionSummary[];
|
|
25
25
|
}
|
|
26
|
-
export interface
|
|
26
|
+
export interface WorkerWorkspaceRef {
|
|
27
27
|
path: string;
|
|
28
|
-
kind:
|
|
28
|
+
kind: WorkerWorkspaceKind;
|
|
29
29
|
repository?: string;
|
|
30
30
|
branch?: string;
|
|
31
31
|
worktree?: string;
|
|
32
|
-
|
|
32
|
+
workspace?: string;
|
|
33
33
|
baseRevision?: string;
|
|
34
34
|
environment?: SymphonyWorkerEnvironmentRef;
|
|
35
35
|
}
|
|
@@ -147,7 +147,7 @@ export interface SymphonySessionRecord extends SymphonyChatThreadRef {
|
|
|
147
147
|
secretaryAutoEnabled?: boolean;
|
|
148
148
|
status: SymphonySessionStatus;
|
|
149
149
|
cwd: string;
|
|
150
|
-
|
|
150
|
+
workspaceRef?: WorkerWorkspaceRef;
|
|
151
151
|
target: SymphonyDelegationTarget;
|
|
152
152
|
model?: string;
|
|
153
153
|
supervisor?: SymphonySupervisorPolicy;
|
|
@@ -180,18 +180,18 @@ export interface SymphonyWorkerSpec extends Partial<SymphonyDelegationTarget> {
|
|
|
180
180
|
acceptanceCriteria?: string[];
|
|
181
181
|
model?: string;
|
|
182
182
|
supervisorIntervalMs?: number;
|
|
183
|
-
workspace?: Partial<
|
|
183
|
+
workspace?: Partial<WorkerWorkspaceRef>;
|
|
184
184
|
}
|
|
185
185
|
export interface CreateSymphonyRunPlanInput {
|
|
186
186
|
objective: string;
|
|
187
187
|
title?: string;
|
|
188
188
|
acceptanceCriteria?: string[];
|
|
189
189
|
workspacePath: string;
|
|
190
|
-
workspaceKind?:
|
|
190
|
+
workspaceKind?: WorkerWorkspaceKind;
|
|
191
191
|
repository?: string;
|
|
192
192
|
branch?: string;
|
|
193
193
|
worktree?: string;
|
|
194
|
-
|
|
194
|
+
workspace?: string;
|
|
195
195
|
baseRevision?: string;
|
|
196
196
|
environment?: Partial<SymphonyWorkerEnvironmentRef>;
|
|
197
197
|
backend: AutoModeWorkerBackend;
|
|
@@ -242,7 +242,7 @@ export declare function renderSymphonyRuntimePrompt(input: {
|
|
|
242
242
|
task: string;
|
|
243
243
|
objective: string;
|
|
244
244
|
acceptanceCriteria?: string[];
|
|
245
|
-
workspace:
|
|
245
|
+
workspace: WorkerWorkspaceRef;
|
|
246
246
|
backend: AutoModeWorkerBackend;
|
|
247
247
|
mode: AutoModeMode;
|
|
248
248
|
secretaryAutoEnabled?: boolean;
|
|
@@ -72,7 +72,7 @@ export function createRunPlan(input) {
|
|
|
72
72
|
...(normalizeOptionalText(input.repository) ? { repository: normalizeOptionalText(input.repository) } : {}),
|
|
73
73
|
...(normalizeOptionalText(input.branch) ? { branch: normalizeOptionalText(input.branch) } : {}),
|
|
74
74
|
...(normalizeOptionalText(input.worktree) ? { worktree: normalizeOptionalText(input.worktree) } : {}),
|
|
75
|
-
...(normalizeOptionalText(input.
|
|
75
|
+
...(normalizeOptionalText(input.workspace) ? { workspace: normalizeOptionalText(input.workspace) } : {}),
|
|
76
76
|
...(normalizeOptionalText(input.baseRevision) ? { baseRevision: normalizeOptionalText(input.baseRevision) } : {}),
|
|
77
77
|
environment: normalizeSymphonyWorkerEnvironment(input.environment, input.backend),
|
|
78
78
|
};
|
|
@@ -146,7 +146,7 @@ export function createRunPlan(input) {
|
|
|
146
146
|
...(input.secretaryAutoEnabled !== undefined ? { secretaryAutoEnabled: input.secretaryAutoEnabled } : {}),
|
|
147
147
|
status: 'planned',
|
|
148
148
|
cwd: workerWorkspace.path,
|
|
149
|
-
|
|
149
|
+
workspaceRef: workerWorkspace,
|
|
150
150
|
target,
|
|
151
151
|
...(spec.model ? { model: spec.model } : {}),
|
|
152
152
|
...(spec.supervisor ? { supervisor: spec.supervisor } : {}),
|
|
@@ -239,7 +239,7 @@ export function renderSymphonyRuntimePrompt(input) {
|
|
|
239
239
|
...(workThread ? [`Work thread: ${workThread}`] : []),
|
|
240
240
|
`Workspace: ${input.workspace.path}`,
|
|
241
241
|
`Workspace kind: ${input.workspace.kind}`,
|
|
242
|
-
...(input.workspace.
|
|
242
|
+
...(input.workspace.workspace ? [`Workspace resource: ${input.workspace.workspace}`] : []),
|
|
243
243
|
...(input.workspace.repository ? [`Workspace repository: ${input.workspace.repository}`] : []),
|
|
244
244
|
...(input.workspace.branch ? [`Workspace branch: ${input.workspace.branch}`] : []),
|
|
245
245
|
...(input.workspace.baseRevision ? [`Workspace base revision: ${input.workspace.baseRevision}`] : []),
|
|
@@ -406,7 +406,7 @@ function normalizeSymphonyWorkerWorkspace(root, override, backend) {
|
|
|
406
406
|
...(normalizeOptionalText(override?.repository ?? root.repository) ? { repository: normalizeOptionalText(override?.repository ?? root.repository) } : {}),
|
|
407
407
|
...(normalizeOptionalText(override?.branch ?? root.branch) ? { branch: normalizeOptionalText(override?.branch ?? root.branch) } : {}),
|
|
408
408
|
...(normalizeOptionalText(override?.worktree ?? root.worktree) ? { worktree: normalizeOptionalText(override?.worktree ?? root.worktree) } : {}),
|
|
409
|
-
...(normalizeOptionalText(override?.
|
|
409
|
+
...(normalizeOptionalText(override?.workspace ?? root.workspace) ? { workspace: normalizeOptionalText(override?.workspace ?? root.workspace) } : {}),
|
|
410
410
|
...(normalizeOptionalText(override?.baseRevision ?? root.baseRevision) ? { baseRevision: normalizeOptionalText(override?.baseRevision ?? root.baseRevision) } : {}),
|
|
411
411
|
environment: normalizeSymphonyWorkerEnvironment(override?.environment ?? root.environment, backend),
|
|
412
412
|
};
|