@atolis-hq/wake 0.4.29 → 0.4.31
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/src/bootstrap/integration-runtime.js +3 -1
- package/dist/src/bootstrap/version.js +1 -1
- package/dist/src/conversations/contracts/events.js +2 -0
- package/dist/src/conversations/contracts/identifiers.d.ts +1 -0
- package/dist/src/conversations/contracts/identifiers.js +3 -0
- package/dist/src/conversations/contracts/views.d.ts +4 -0
- package/dist/src/integrations/github/application/inbound-translator.d.ts +0 -1
- package/dist/src/integrations/github/application/inbound-translator.js +6 -15
- package/dist/src/integrations/github/infrastructure/source.js +1 -1
- package/dist/src/orchestration/application/conversation-command-reactor.d.ts +6 -0
- package/dist/src/orchestration/application/conversation-command-reactor.js +59 -0
- package/dist/src/orchestration/index.d.ts +1 -0
- package/dist/src/orchestration/index.js +1 -0
- package/package.json +2 -1
|
@@ -4,7 +4,7 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { ControlStreamKind, ScheduleService, createIntakePipeline, createRunnerPipeline, createWorkCancellationPolicy, } from '../control-plane/index.js';
|
|
5
5
|
import { RunRepository, createRuntimeMemoryProfile, } from '../execution/index.js';
|
|
6
6
|
import { AgentRunPublicationReactor, ArtifactRegistrationReactor, DeliveryOutcomeReactor, DeliveryService, IntegrationStreamKind, PollService, ProviderRegistry, deliveryProjectionDefinitions, fakeProviderDefinition, } from '../integrations/index.js';
|
|
7
|
-
import { compileWorkflowSelectors, createPullRequestTransitionEvidence, createResourceTransitionReactor, createWatchReactor, createWatchReconciler, selectWorkflow, workflowName, } from '../orchestration/index.js';
|
|
7
|
+
import { compileWorkflowSelectors, createConversationCommandReactor, createPullRequestTransitionEvidence, createResourceTransitionReactor, createWatchReactor, createWatchReconciler, selectWorkflow, workflowName, } from '../orchestration/index.js';
|
|
8
8
|
import { BuiltInResourceCapability, resourceId, } from '../resources/index.js';
|
|
9
9
|
import { hydrateFakeProviderEvidence } from './fake-provider-files.js';
|
|
10
10
|
import { createRuntimeProjectionSubscriptions, } from './projection-runtime.js';
|
|
@@ -109,6 +109,7 @@ export async function composeIntegrationRuntime(input) {
|
|
|
109
109
|
return operation();
|
|
110
110
|
});
|
|
111
111
|
const outcomes = new DeliveryOutcomeReactor(input.journal, input.orchestration, input.projections, input.processorState, input.conversations, input.subscriptionRunSerialiser);
|
|
112
|
+
const conversationCommands = createConversationCommandReactor(input.orchestration);
|
|
112
113
|
// Only poll hits a rate-limited external API, so only this half of the
|
|
113
114
|
// Tick needs a backing-off host; see bootstrap/surface-cli-applications.ts.
|
|
114
115
|
// Inbound translation reads durable provider facts through its own services,
|
|
@@ -163,6 +164,7 @@ export async function composeIntegrationRuntime(input) {
|
|
|
163
164
|
artifacts.processor,
|
|
164
165
|
outcomes.processor,
|
|
165
166
|
agentRunPublications.processor,
|
|
167
|
+
conversationCommands.processor,
|
|
166
168
|
...providers.map((provider) => provider.inbound.processor),
|
|
167
169
|
],
|
|
168
170
|
providers,
|
|
@@ -124,6 +124,6 @@ export function resolveWakeVersion(options = {}) {
|
|
|
124
124
|
return `g${headHash.slice(0, 7)}`;
|
|
125
125
|
return '0.1.0-dev';
|
|
126
126
|
}
|
|
127
|
-
export const wakeVersion = "v0.4.
|
|
127
|
+
export const wakeVersion = "v0.4.31";
|
|
128
128
|
/** The registry-installable version used by packaged sandbox images. */
|
|
129
129
|
export const wakePackageVersion = packageVersion(defaultRepoRoot) ?? wakeVersion;
|
|
@@ -39,6 +39,8 @@ const origin = z.discriminatedUnion('kind', [
|
|
|
39
39
|
resourceId: z.string().min(1),
|
|
40
40
|
threadId: z.string().min(1),
|
|
41
41
|
messageId: z.string().min(1),
|
|
42
|
+
authorized: z.boolean().optional(),
|
|
43
|
+
capabilities: z.array(z.string().min(1)).readonly().optional(),
|
|
42
44
|
location: z
|
|
43
45
|
.object({
|
|
44
46
|
path: z.string().min(1),
|
|
@@ -3,3 +3,4 @@ import type { WorkItemId } from '../../work/index.js';
|
|
|
3
3
|
export type ConversationId = Brand<string, 'ConversationId'>;
|
|
4
4
|
export declare function conversationId(value: string): ConversationId;
|
|
5
5
|
export declare function conversationIdForWorkItem(workItemId: WorkItemId): ConversationId;
|
|
6
|
+
export declare function workItemIdForConversation(conversationIdValue: ConversationId): WorkItemId;
|
|
@@ -6,3 +6,6 @@ export function conversationId(value) {
|
|
|
6
6
|
export function conversationIdForWorkItem(workItemId) {
|
|
7
7
|
return conversationId(`conversation-${String(workItemId).slice('work-'.length)}`);
|
|
8
8
|
}
|
|
9
|
+
export function workItemIdForConversation(conversationIdValue) {
|
|
10
|
+
return `work-${String(conversationIdValue).slice('conversation-'.length)}`;
|
|
11
|
+
}
|
|
@@ -16,6 +16,10 @@ export type ConversationEntryOrigin = {
|
|
|
16
16
|
readonly resourceId: string;
|
|
17
17
|
readonly threadId: string;
|
|
18
18
|
readonly messageId: string;
|
|
19
|
+
/** Authority established by the receiving surface before the entry is recorded. */
|
|
20
|
+
readonly authorized?: boolean | undefined;
|
|
21
|
+
/** Commands available to this entry's receiving surface. */
|
|
22
|
+
readonly capabilities?: readonly string[] | undefined;
|
|
19
23
|
readonly location?: {
|
|
20
24
|
readonly path: string;
|
|
21
25
|
readonly line: number;
|
|
@@ -75,7 +75,6 @@ export declare class InboundTranslator {
|
|
|
75
75
|
private recordConversationDeferred;
|
|
76
76
|
private appendConversationRecordFact;
|
|
77
77
|
private recordConversationEntry;
|
|
78
|
-
private applyConversationCommand;
|
|
79
78
|
private failureRecorded;
|
|
80
79
|
private retryRecorded;
|
|
81
80
|
private recordTranslationRecovery;
|
|
@@ -110,7 +110,8 @@ export class InboundTranslator {
|
|
|
110
110
|
if (isGitHubAdapterEventType(owned, GitHubEventType.WorkObserved))
|
|
111
111
|
await this.apply(owned);
|
|
112
112
|
if (isGitHubAdapterEventType(owned, GitHubEventType.CommentObserved)) {
|
|
113
|
-
if (
|
|
113
|
+
if (owned.event.payload.reviewKind === 'formal' &&
|
|
114
|
+
!(await this.suppressWorkItemEffects(owned)))
|
|
114
115
|
await applyReviewSignal({
|
|
115
116
|
event: owned,
|
|
116
117
|
journal: this.journal,
|
|
@@ -226,7 +227,7 @@ export class InboundTranslator {
|
|
|
226
227
|
entry.origin.messageId === externalId);
|
|
227
228
|
if (existing?.entries.some((entry) => entry.representations.some((representation) => representation.resourceId === resource.resourceId &&
|
|
228
229
|
representation.externalId === externalId)))
|
|
229
|
-
return
|
|
230
|
+
return;
|
|
230
231
|
if (priorEntry !== undefined) {
|
|
231
232
|
if (priorEntry.body !== event.event.payload.body)
|
|
232
233
|
await this.conversations.revise({
|
|
@@ -234,7 +235,7 @@ export class InboundTranslator {
|
|
|
234
235
|
entryId: priorEntry.entryId,
|
|
235
236
|
body: event.event.payload.body,
|
|
236
237
|
}, commandContext(event));
|
|
237
|
-
return
|
|
238
|
+
return;
|
|
238
239
|
}
|
|
239
240
|
await this.conversations.record({
|
|
240
241
|
conversationId,
|
|
@@ -247,24 +248,14 @@ export class InboundTranslator {
|
|
|
247
248
|
resourceId: resource.resourceId,
|
|
248
249
|
threadId: resource.externalKey.key,
|
|
249
250
|
messageId: externalId,
|
|
251
|
+
authorized: isAuthorizedConversationActor(event),
|
|
252
|
+
capabilities: this.conversationCapabilities,
|
|
250
253
|
...(event.event.payload.reviewKind !== 'issue' ||
|
|
251
254
|
event.event.payload.location === undefined
|
|
252
255
|
? {}
|
|
253
256
|
: { location: event.event.payload.location }),
|
|
254
257
|
},
|
|
255
258
|
}, commandContext(event));
|
|
256
|
-
await this.applyConversationCommand(correlation.workItemId, event);
|
|
257
|
-
}
|
|
258
|
-
async applyConversationCommand(workItemId, event) {
|
|
259
|
-
// Native formal reviews already carry their own verified decision and workflow signal.
|
|
260
|
-
if (event.event.payload.reviewKind !== 'issue')
|
|
261
|
-
return;
|
|
262
|
-
await this.orchestration?.applyConversationCommand(workItemId, {
|
|
263
|
-
body: event.event.payload.body,
|
|
264
|
-
actorId: event.event.payload.actor.id,
|
|
265
|
-
capabilities: this.conversationCapabilities,
|
|
266
|
-
authorized: isAuthorizedConversationActor(event),
|
|
267
|
-
}, commandContext(event));
|
|
268
259
|
}
|
|
269
260
|
async failureRecorded(sourceEventId) {
|
|
270
261
|
return (await this.journal.readStream(integrationStream(this.adapter))).some((event) => {
|
|
@@ -116,7 +116,7 @@ async function pollRepository(input) {
|
|
|
116
116
|
}).poll(signal),
|
|
117
117
|
reviewEventsFor(context, pullRequestPayloads),
|
|
118
118
|
reviewCommentEventsFor(context, pullRequestPayloads),
|
|
119
|
-
issueCommentEventsFor(context, issues, since),
|
|
119
|
+
issueCommentEventsFor(context, [...issues, ...pullRequestPayloads], since),
|
|
120
120
|
]);
|
|
121
121
|
return {
|
|
122
122
|
repository: context.repository,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type EventProcessor } from '@atolis-hq/eventing';
|
|
2
|
+
import type { OrchestrationService } from './orchestration-service.js';
|
|
3
|
+
/** Applies human commands only after their external message is canonical conversation history. */
|
|
4
|
+
export declare function createConversationCommandReactor(orchestration: OrchestrationService): {
|
|
5
|
+
readonly processor: EventProcessor;
|
|
6
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { EventActorKind, EventProcessorCategory, EventProcessorReplayPolicy, correlationId, defineEventProcessor, } from '@atolis-hq/eventing';
|
|
2
|
+
import { ConversationEventType, ConversationOriginKind, selectConversationEvent, workItemIdForConversation, } from '../../conversations/index.js';
|
|
3
|
+
import { conversationCommand } from './conversation-command.js';
|
|
4
|
+
/** Applies human commands only after their external message is canonical conversation history. */
|
|
5
|
+
export function createConversationCommandReactor(orchestration) {
|
|
6
|
+
return {
|
|
7
|
+
processor: defineEventProcessor({
|
|
8
|
+
consumer: 'reactor:orchestration.conversation-command',
|
|
9
|
+
name: 'orchestration.conversation-command',
|
|
10
|
+
owner: 'orchestration',
|
|
11
|
+
category: EventProcessorCategory.Reactor,
|
|
12
|
+
replayPolicy: EventProcessorReplayPolicy.Idempotent,
|
|
13
|
+
select(event) {
|
|
14
|
+
const conversation = selectConversationEvent(event);
|
|
15
|
+
if (conversation?.event.eventType !== ConversationEventType.EntryRecorded)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
conversationId: conversation.stream.id,
|
|
19
|
+
eventId: conversation.event.eventId,
|
|
20
|
+
correlationId: conversation.event.correlationId,
|
|
21
|
+
occurredAt: conversation.event.occurredAt,
|
|
22
|
+
entry: conversation.event.payload,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
async handle(event) {
|
|
26
|
+
if (event === null)
|
|
27
|
+
return;
|
|
28
|
+
const { entry } = event;
|
|
29
|
+
if (entry.origin.kind !== ConversationOriginKind.External)
|
|
30
|
+
return;
|
|
31
|
+
const workItemId = workItemIdForConversation(event.conversationId);
|
|
32
|
+
const input = {
|
|
33
|
+
body: entry.body,
|
|
34
|
+
actorId: entry.origin.actorId,
|
|
35
|
+
capabilities: (entry.origin.capabilities ?? []),
|
|
36
|
+
authorized: entry.origin.authorized === true,
|
|
37
|
+
};
|
|
38
|
+
await orchestration.applyConversationCommand(workItemId, input, {
|
|
39
|
+
commandId: `${event.eventId}:conversation-command`,
|
|
40
|
+
correlationId: correlationId(event.correlationId),
|
|
41
|
+
occurredAt: event.occurredAt,
|
|
42
|
+
actor: { kind: EventActorKind.Integration, id: entry.origin.adapter },
|
|
43
|
+
});
|
|
44
|
+
if (conversationCommand(entry.body) !== null || !input.authorized)
|
|
45
|
+
return;
|
|
46
|
+
for (const workflow of await orchestration.listAll()) {
|
|
47
|
+
if (workflow.workItemId !== workItemId)
|
|
48
|
+
continue;
|
|
49
|
+
await orchestration.resumeBlockedStageForChanges(workflow.workflowInstanceId, {
|
|
50
|
+
commandId: `${event.eventId}:conversation-reply`,
|
|
51
|
+
correlationId: correlationId(event.correlationId),
|
|
52
|
+
occurredAt: event.occurredAt,
|
|
53
|
+
actor: { kind: EventActorKind.Integration, id: entry.origin.adapter },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -11,6 +11,7 @@ export * from './application/signal-reactor.js';
|
|
|
11
11
|
export * from './application/watch-reactor.js';
|
|
12
12
|
export * from './application/trigger-workflow-instance.js';
|
|
13
13
|
export * from './application/conversation-command.js';
|
|
14
|
+
export * from './application/conversation-command-reactor.js';
|
|
14
15
|
export * from './application/workflow-definition-registry.js';
|
|
15
16
|
export * from './contracts/activity-outcome.js';
|
|
16
17
|
export * from './contracts/commands.js';
|
|
@@ -11,6 +11,7 @@ export * from './application/signal-reactor.js';
|
|
|
11
11
|
export * from './application/watch-reactor.js';
|
|
12
12
|
export * from './application/trigger-workflow-instance.js';
|
|
13
13
|
export * from './application/conversation-command.js';
|
|
14
|
+
export * from './application/conversation-command-reactor.js';
|
|
14
15
|
export * from './application/workflow-definition-registry.js';
|
|
15
16
|
export * from './contracts/activity-outcome.js';
|
|
16
17
|
export * from './contracts/commands.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atolis-hq/wake",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.31",
|
|
4
4
|
"description": "Local autonomous agent control plane for software development",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"smoke:codex": "tsx --tsconfig tsconfig.source.json src/main.ts smoke codex",
|
|
70
70
|
"smoke:cursor": "tsx --tsconfig tsconfig.source.json src/main.ts smoke cursor",
|
|
71
71
|
"verify": "npm run check:catalogue && npm run check:scenarios && npm run check:specs:report && npm run lint:architecture && npm run lint && npm run format:check && npm run check:source-resolution && npm run build && npm run test:unit",
|
|
72
|
+
"verify:agent": "npm run verify && npm run test:architecture && npm run test:integration",
|
|
72
73
|
"verify:ci": "npm run verify && npm run test:architecture && npm run check:workspace-packages && npm run test:integration && npm run test:e2e && npm run knip && npm run test:web"
|
|
73
74
|
},
|
|
74
75
|
"dependencies": {
|