gestalt-mobile 0.41.2 → 0.42.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.
- package/README.md +13 -0
- package/dist/client/assets/{index-9uZwieND.js → index-BRly-q56.js} +23 -23
- package/dist/client/index.html +1 -1
- package/dist/server/server/cli.js +47 -0
- package/dist/server/server/composition.contracts.js +27 -15
- package/dist/server/server/composition.js +62 -5
- package/dist/server/server/features/agent-activity/model.js +8 -0
- package/dist/server/server/features/autopilot/application/policy.js +4 -4
- package/dist/server/server/features/autopilot/application/service.js +149 -22
- package/dist/server/server/features/autopilot/domain/supervised-lifecycle.js +15 -4
- package/dist/server/server/features/control-plane-trace/export-trace.js +90 -0
- package/dist/server/server/features/org-plan-attention/resolve/endpoint.js +5 -3
- package/dist/server/server/features/skills/list-available/endpoint.js +2 -1
- package/dist/server/server/features/skills/model/skill-profile.js +8 -4
- package/dist/server/server/platform/catalog/profile-command.js +2 -12
- package/dist/server/server/platform/codex/activity-facts.js +2 -0
- package/dist/server/server/platform/codex/codex-process-launcher.js +1 -1
- package/dist/server/server/platform/codex/session-runtime.js +16 -8
- package/dist/server/shared/contracts/org-plan-attention.js +35 -6
- package/dist/server/shared/contracts/org-plan-checkpoint.js +2 -69
- package/package.json +1 -1
|
@@ -17,10 +17,15 @@ import { threadPlanName } from './thread-plan-name.js';
|
|
|
17
17
|
import { WriterAcquisitionError, } from '../../features/sessions/application/writer-acquisition.js';
|
|
18
18
|
import { isCodexThreadWriterBusy, isMissingCodexThreadRollout } from './json-rpc-client.js';
|
|
19
19
|
import { resolvedServerRequestId } from './server-request.js';
|
|
20
|
+
/** Sticky thread config keeps skill paths out of the app-server process argv. */
|
|
21
|
+
export function threadSkillConfig(skillsConfig) {
|
|
22
|
+
return skillsConfig === undefined ? {} : { config: { skills: { config: skillsConfig } } };
|
|
23
|
+
}
|
|
20
24
|
/** One private owner for every resource acquired for a live Codex child. */
|
|
21
25
|
class SessionResource {
|
|
22
26
|
sessionId;
|
|
23
27
|
process;
|
|
28
|
+
skillsConfig;
|
|
24
29
|
planStatusLease;
|
|
25
30
|
planMeasurementToken;
|
|
26
31
|
unregister;
|
|
@@ -39,9 +44,10 @@ class SessionResource {
|
|
|
39
44
|
completedProcessActions = new Map();
|
|
40
45
|
turnThreads = new Map();
|
|
41
46
|
childThreads = new Set();
|
|
42
|
-
constructor(sessionId, process, planStatusLease, planMeasurementToken, unregister, onDisposed) {
|
|
47
|
+
constructor(sessionId, process, skillsConfig, planStatusLease, planMeasurementToken, unregister, onDisposed) {
|
|
43
48
|
this.sessionId = sessionId;
|
|
44
49
|
this.process = process;
|
|
50
|
+
this.skillsConfig = skillsConfig;
|
|
45
51
|
this.planStatusLease = planStatusLease;
|
|
46
52
|
this.planMeasurementToken = planMeasurementToken;
|
|
47
53
|
this.unregister = unregister;
|
|
@@ -117,7 +123,7 @@ export class CodexSessionRuntime {
|
|
|
117
123
|
clientInfo: { name: 'gestalt-mobile', version: '0.1.0' },
|
|
118
124
|
capabilities: { experimentalApi: true },
|
|
119
125
|
});
|
|
120
|
-
const startedThreadId = await this.startThread(resource.process, session);
|
|
126
|
+
const startedThreadId = await this.startThread(resource.process, session, resource.skillsConfig);
|
|
121
127
|
resource.threadId = startedThreadId;
|
|
122
128
|
this.sessions.set(session.id, resource);
|
|
123
129
|
await this.writePendingThreadName(session.id);
|
|
@@ -671,6 +677,7 @@ export class CodexSessionRuntime {
|
|
|
671
677
|
await resource.process.rpc.request('thread/resume', {
|
|
672
678
|
threadId: session.threadId,
|
|
673
679
|
cwd: session.workspacePath,
|
|
680
|
+
...threadSkillConfig(resource.skillsConfig),
|
|
674
681
|
...(session.executionPolicy?.approvalPolicy
|
|
675
682
|
? { approvalPolicy: session.executionPolicy.approvalPolicy }
|
|
676
683
|
: {}),
|
|
@@ -692,7 +699,7 @@ export class CodexSessionRuntime {
|
|
|
692
699
|
catch (error) {
|
|
693
700
|
if (!canRebindMissingRollout(session, error))
|
|
694
701
|
throw error;
|
|
695
|
-
const replacementThreadId = await this.startThread(resource.process, session);
|
|
702
|
+
const replacementThreadId = await this.startThread(resource.process, session, resource.skillsConfig);
|
|
696
703
|
result = rebindMissingRollout(session, error, replacementThreadId, now);
|
|
697
704
|
}
|
|
698
705
|
resource.threadId = result.session.threadId;
|
|
@@ -760,12 +767,13 @@ export class CodexSessionRuntime {
|
|
|
760
767
|
reject(new Error('CODEX_SERVER_REQUEST_UNSUPPORTED'));
|
|
761
768
|
});
|
|
762
769
|
}
|
|
763
|
-
async startThread(process, session) {
|
|
764
|
-
return decodeThreadStart(await process.rpc.request('thread/start', this.threadStartParams(session)));
|
|
770
|
+
async startThread(process, session, skillsConfig) {
|
|
771
|
+
return decodeThreadStart(await process.rpc.request('thread/start', this.threadStartParams(session, skillsConfig)));
|
|
765
772
|
}
|
|
766
|
-
threadStartParams(session) {
|
|
773
|
+
threadStartParams(session, skillsConfig) {
|
|
767
774
|
return {
|
|
768
775
|
cwd: session.workspacePath,
|
|
776
|
+
...threadSkillConfig(skillsConfig),
|
|
769
777
|
approvalPolicy: session.executionPolicy?.approvalPolicy ?? 'on-request',
|
|
770
778
|
dynamicTools: [
|
|
771
779
|
gestaltQuizDynamicTool,
|
|
@@ -792,10 +800,10 @@ export class CodexSessionRuntime {
|
|
|
792
800
|
: undefined;
|
|
793
801
|
try {
|
|
794
802
|
const token = randomUUID();
|
|
803
|
+
const skillsConfig = await this.resolveSkills?.(session);
|
|
795
804
|
const process = this.launch({
|
|
796
805
|
profile: session.profile,
|
|
797
806
|
cwd: session.workspacePath,
|
|
798
|
-
skillsConfig: await this.resolveSkills?.(session),
|
|
799
807
|
...(lease || this.planMeasurementBaseUrl
|
|
800
808
|
? {
|
|
801
809
|
environment: {
|
|
@@ -812,7 +820,7 @@ export class CodexSessionRuntime {
|
|
|
812
820
|
}
|
|
813
821
|
: {}),
|
|
814
822
|
});
|
|
815
|
-
const resource = new SessionResource(session.id, process, lease, token, [], () => {
|
|
823
|
+
const resource = new SessionResource(session.id, process, skillsConfig, lease, token, [], () => {
|
|
816
824
|
if (this.sessions.get(session.id) === resource)
|
|
817
825
|
this.sessions.delete(session.id);
|
|
818
826
|
});
|
|
@@ -41,6 +41,12 @@ export const gestaltOrgPlanAttentionDynamicTool = {
|
|
|
41
41
|
summary: { type: 'string', minLength: 1, maxLength: 600 },
|
|
42
42
|
requestedAction: { type: 'string', minLength: 1, maxLength: 600 },
|
|
43
43
|
resumeCondition: { type: 'string', enum: orgPlanAttentionResumeConditions },
|
|
44
|
+
executorReplacement: {
|
|
45
|
+
type: 'object',
|
|
46
|
+
additionalProperties: false,
|
|
47
|
+
required: ['canonicalTaskName'],
|
|
48
|
+
properties: { canonicalTaskName: { type: 'string', pattern: '^l[1-9][0-9]*$' } },
|
|
49
|
+
},
|
|
44
50
|
},
|
|
45
51
|
oneOf: orgPlanAttentionReasons.map((reason) => ({
|
|
46
52
|
properties: {
|
|
@@ -66,19 +72,31 @@ export function parseOrgPlanAttention(value) {
|
|
|
66
72
|
requestedAction: `Satisfy the ${value.resumeCondition} resume condition, then resume or disable Autopilot.`,
|
|
67
73
|
resumeCondition: value.resumeCondition,
|
|
68
74
|
};
|
|
69
|
-
if (keys.length !== 4)
|
|
75
|
+
if (keys.length !== 4 && keys.length !== 5)
|
|
76
|
+
return null;
|
|
77
|
+
if (keys.some((key) => ![
|
|
78
|
+
'reason',
|
|
79
|
+
'summary',
|
|
80
|
+
'requestedAction',
|
|
81
|
+
'resumeCondition',
|
|
82
|
+
'executorReplacement',
|
|
83
|
+
].includes(key)))
|
|
70
84
|
return null;
|
|
85
|
+
const executorReplacement = parseExecutorReplacement(value.executorReplacement);
|
|
71
86
|
if (!isReason(value.reason) ||
|
|
72
87
|
!isBoundedText(value.summary, 600) ||
|
|
73
88
|
!isBoundedText(value.requestedAction, 600) ||
|
|
74
89
|
!isResumeCondition(value.resumeCondition) ||
|
|
75
|
-
orgPlanAttentionResumeConditionByReason[value.reason] !== value.resumeCondition
|
|
90
|
+
orgPlanAttentionResumeConditionByReason[value.reason] !== value.resumeCondition ||
|
|
91
|
+
(value.executorReplacement !== undefined && !executorReplacement) ||
|
|
92
|
+
(executorReplacement && value.reason !== 'permissionRequired'))
|
|
76
93
|
return null;
|
|
77
94
|
return {
|
|
78
95
|
reason: value.reason,
|
|
79
96
|
summary: value.summary,
|
|
80
97
|
requestedAction: value.requestedAction,
|
|
81
98
|
resumeCondition: value.resumeCondition,
|
|
99
|
+
...(executorReplacement ? { executorReplacement } : {}),
|
|
82
100
|
};
|
|
83
101
|
}
|
|
84
102
|
export function parseOrgPlanAttentionResponse(value) {
|
|
@@ -108,21 +126,32 @@ export function toOrgPlanAttentionAcknowledgement(acknowledgement = { accepted:
|
|
|
108
126
|
};
|
|
109
127
|
}
|
|
110
128
|
export function isOrgPlanAttentionToolResponse(value) {
|
|
129
|
+
return parseOrgPlanAttentionToolResponse(value) !== null;
|
|
130
|
+
}
|
|
131
|
+
export function parseOrgPlanAttentionToolResponse(value) {
|
|
111
132
|
if (!isRecord(value) || value.success !== true || !Array.isArray(value.contentItems))
|
|
112
|
-
return
|
|
133
|
+
return null;
|
|
113
134
|
const item = value.contentItems[0];
|
|
114
135
|
if (value.contentItems.length !== 1 ||
|
|
115
136
|
!isRecord(item) ||
|
|
116
137
|
item.type !== 'inputText' ||
|
|
117
138
|
typeof item.text !== 'string')
|
|
118
|
-
return
|
|
139
|
+
return null;
|
|
119
140
|
try {
|
|
120
|
-
return parseOrgPlanAttentionResponse(JSON.parse(item.text))
|
|
141
|
+
return parseOrgPlanAttentionResponse(JSON.parse(item.text));
|
|
121
142
|
}
|
|
122
143
|
catch {
|
|
123
|
-
return
|
|
144
|
+
return null;
|
|
124
145
|
}
|
|
125
146
|
}
|
|
147
|
+
function parseExecutorReplacement(value) {
|
|
148
|
+
if (!isRecord(value) || Object.keys(value).length !== 1)
|
|
149
|
+
return null;
|
|
150
|
+
return typeof value.canonicalTaskName === 'string' &&
|
|
151
|
+
/^l[1-9][0-9]*$/.test(value.canonicalTaskName)
|
|
152
|
+
? { canonicalTaskName: value.canonicalTaskName }
|
|
153
|
+
: null;
|
|
154
|
+
}
|
|
126
155
|
function isReason(value) {
|
|
127
156
|
return (typeof value === 'string' && orgPlanAttentionReasons.includes(value));
|
|
128
157
|
}
|
|
@@ -10,81 +10,14 @@ const record = (value) => typeof value === 'object' && value !== null && !Array.
|
|
|
10
10
|
export const gestaltOrgPlanCheckpointDynamicTool = {
|
|
11
11
|
type: 'function',
|
|
12
12
|
name: GESTALT_ORG_PLAN_CHECKPOINT_TOOL_NAME,
|
|
13
|
-
description: 'Record a validated supervised Org Plan report boundary.
|
|
13
|
+
description: 'Record a validated supervised Org Plan report boundary. Send only the boundary kind; Mobile derives and validates all details from authoritative control state.',
|
|
14
14
|
inputSchema: {
|
|
15
15
|
type: 'object',
|
|
16
16
|
additionalProperties: false,
|
|
17
|
-
required: ['
|
|
17
|
+
required: ['kind'],
|
|
18
18
|
properties: {
|
|
19
|
-
version: { const: 1 },
|
|
20
19
|
kind: { type: 'string', enum: ['l2Completed', 'l1Accepted', 'terminalReviewAccepted'] },
|
|
21
|
-
planIdentity: { type: 'string', minLength: 1, maxLength: 128 },
|
|
22
|
-
l1Id: { type: 'string', minLength: 1, maxLength: 128 },
|
|
23
|
-
l2Id: { type: 'string', minLength: 1, maxLength: 128 },
|
|
24
|
-
position: { type: 'string', pattern: '^L[1-9][0-9]*(\\.[1-9][0-9]*)?$', maxLength: 32 },
|
|
25
|
-
status: { const: 'DONE' },
|
|
26
|
-
verdict: { const: 'ACCEPT' },
|
|
27
|
-
commit: {
|
|
28
|
-
oneOf: [
|
|
29
|
-
{
|
|
30
|
-
type: 'object',
|
|
31
|
-
additionalProperties: false,
|
|
32
|
-
required: ['kind', 'subject', 'shortHash'],
|
|
33
|
-
properties: {
|
|
34
|
-
kind: { const: 'created' },
|
|
35
|
-
subject: { type: 'string', minLength: 1, maxLength: 160 },
|
|
36
|
-
shortHash: { type: 'string', pattern: '^[0-9a-f]{7,16}$' },
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: 'object',
|
|
41
|
-
additionalProperties: false,
|
|
42
|
-
required: ['kind'],
|
|
43
|
-
properties: { kind: { const: 'notRequired' } },
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
findings: { type: 'string', minLength: 1, maxLength: 600 },
|
|
48
|
-
changes: { type: 'string', minLength: 1, maxLength: 600 },
|
|
49
|
-
files: { type: 'string', minLength: 1, maxLength: 600 },
|
|
50
|
-
tests: { type: 'string', minLength: 1, maxLength: 600 },
|
|
51
20
|
},
|
|
52
|
-
oneOf: [
|
|
53
|
-
{
|
|
54
|
-
properties: { kind: { const: 'l2Completed' } },
|
|
55
|
-
required: ['l1Id', 'l2Id', 'position', 'status', 'changes', 'files', 'tests'],
|
|
56
|
-
not: {
|
|
57
|
-
anyOf: [{ required: ['verdict'] }, { required: ['commit'] }, { required: ['findings'] }],
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
properties: { kind: { const: 'l1Accepted' } },
|
|
62
|
-
required: ['l1Id', 'position', 'verdict', 'commit'],
|
|
63
|
-
not: {
|
|
64
|
-
anyOf: [
|
|
65
|
-
{ required: ['l2Id'] },
|
|
66
|
-
{ required: ['status'] },
|
|
67
|
-
{ required: ['changes'] },
|
|
68
|
-
{ required: ['files'] },
|
|
69
|
-
],
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
properties: { kind: { const: 'terminalReviewAccepted' } },
|
|
74
|
-
required: ['verdict'],
|
|
75
|
-
not: {
|
|
76
|
-
anyOf: [
|
|
77
|
-
{ required: ['l1Id'] },
|
|
78
|
-
{ required: ['l2Id'] },
|
|
79
|
-
{ required: ['position'] },
|
|
80
|
-
{ required: ['status'] },
|
|
81
|
-
{ required: ['commit'] },
|
|
82
|
-
{ required: ['changes'] },
|
|
83
|
-
{ required: ['files'] },
|
|
84
|
-
],
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
],
|
|
88
21
|
},
|
|
89
22
|
};
|
|
90
23
|
export function parseOrgPlanCheckpoint(value) {
|