@xfey/tutti 0.1.126 → 0.1.127
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 +2 -0
- package/dist/chat-assistant/diagnostics.d.ts +4 -1
- package/dist/chat-assistant/index.js +15 -6
- package/dist/chat-assistant/language-context.d.ts +8 -0
- package/dist/chat-assistant/language-context.js +41 -0
- package/dist/collaboration-state/communication-language.d.ts +31 -0
- package/dist/collaboration-state/communication-language.js +36 -0
- package/dist/collaboration-state/task-compile-context.js +9 -0
- package/dist/communication-language/index.d.ts +75 -0
- package/dist/communication-language/index.js +122 -0
- package/dist/communication-language/live-smoke-cli.d.ts +2 -0
- package/dist/communication-language/live-smoke-cli.js +368 -0
- package/dist/communication-language/prompt.d.ts +22 -0
- package/dist/communication-language/prompt.js +73 -0
- package/dist/control-plane/communication-language.d.ts +33 -0
- package/dist/control-plane/communication-language.js +72 -0
- package/dist/control-plane/context-sync.js +7 -0
- package/dist/control-plane/follow-up-output.js +25 -4
- package/dist/control-plane/follow-up-start.js +17 -0
- package/dist/control-plane/project-brief-refresh.js +10 -1
- package/dist/control-plane/project-context-bootstrap.d.ts +2 -0
- package/dist/control-plane/project-context-bootstrap.js +8 -0
- package/dist/control-plane/reference-summary-refresh.js +7 -0
- package/dist/control-plane/run-start.js +14 -6
- package/dist/control-plane/scratchpad-refresh-start.d.ts +1 -0
- package/dist/control-plane/scratchpad-refresh-start.js +13 -0
- package/dist/control-plane/scratchpad-refresh.d.ts +2 -0
- package/dist/control-plane/scratchpad-refresh.js +40 -26
- package/dist/control-plane/task-compile-continuation.js +14 -1
- package/dist/control-plane/task-compile-output.js +38 -14
- package/dist/control-plane/task-compile-start.d.ts +1 -0
- package/dist/control-plane/task-compile-start.js +22 -1
- package/dist/control-plane/types.d.ts +2 -0
- package/dist/control-plane/workflows/openai.js +48 -28
- package/dist/control-plane/workflows/types.d.ts +18 -13
- package/dist/prompt-templates/index.d.ts +1 -1
- package/dist/prompt-templates/index.js +2 -0
- package/dist/run-pipeline/task-run-invocation.js +12 -9
- package/migrations/0023_communication_language.sql +14 -0
- package/package.json +1 -1
- package/prompts/README.md +1 -0
- package/prompts/chat-assistant.md +1 -1
- package/prompts/communication-language-result.md +27 -0
- package/prompts/communication-language.md +50 -0
- package/prompts/procedures/follow-up-check.md +1 -1
- package/prompts/procedures/scratchpad-refresh.md +2 -2
- package/prompts/procedures/task-compile.md +1 -1
- package/prompts/prompt-flow-map.md +2 -0
|
@@ -3,7 +3,7 @@ import { rm } from "node:fs/promises";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
5
5
|
import { clarificationAnswerRole } from "@tutti/shared/utils";
|
|
6
|
-
import {
|
|
6
|
+
import { renderLanguageAwarePrompt, languageOutputContract, } from "../../communication-language/prompt.js";
|
|
7
7
|
import { createOpenAiStructuredOutputClient, runOpenAiStructuredOutput, } from "../../providers/openai/sdk-procedure-runner.js";
|
|
8
8
|
import { readOpenAiApiKeyCredential } from "../../providers/openai/credential-store.js";
|
|
9
9
|
import { resolveOpenAiProviderConfig } from "../../providers/openai/provider-config.js";
|
|
@@ -283,13 +283,15 @@ function recordUsage(options, source, result, anchors = {}) {
|
|
|
283
283
|
export function createOpenAiProcedureWorkflowRunner(options) {
|
|
284
284
|
const runner = {
|
|
285
285
|
async runScratchpadRefresh(input, context) {
|
|
286
|
-
const
|
|
286
|
+
const { communication_language: language, ...businessInput } = input;
|
|
287
|
+
const contract = languageOutputContract(SCRATCHPAD_REFRESH_OUTPUT_SCHEMA, isScratchpadRefreshStructuredOutput, language);
|
|
288
|
+
const instructions = renderLanguageAwarePrompt({
|
|
287
289
|
templateKey: "procedures.scratchpad_refresh",
|
|
288
290
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
289
291
|
variables: {
|
|
290
|
-
workflow_input_json:
|
|
292
|
+
workflow_input_json: businessInput,
|
|
291
293
|
},
|
|
292
|
-
});
|
|
294
|
+
}, language, true);
|
|
293
295
|
const result = await runOpenAiStructuredOutput({
|
|
294
296
|
client: options.client,
|
|
295
297
|
model: options.config.default_model,
|
|
@@ -297,23 +299,28 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
297
299
|
input: "Run scratchpad_refresh and return only structured JSON.",
|
|
298
300
|
schemaName: "scratchpad_refresh_output",
|
|
299
301
|
schemaDescription: "Tutti scratchpad_refresh terminal workflow output.",
|
|
300
|
-
schema:
|
|
301
|
-
validate:
|
|
302
|
+
schema: contract.schema,
|
|
303
|
+
validate: contract.validate,
|
|
302
304
|
});
|
|
303
305
|
recordUsage(options, "scratchpad_refresh", result, {
|
|
304
306
|
workflow_ref: context.workflow_ref,
|
|
305
307
|
activity_ref: context.activity_ref,
|
|
306
308
|
});
|
|
307
|
-
|
|
309
|
+
const decoded = contract.unwrap(result.output);
|
|
310
|
+
return {
|
|
311
|
+
...decoded.output.result,
|
|
312
|
+
...(decoded.language === undefined ? {} : { communication_language: decoded.language }),
|
|
313
|
+
};
|
|
308
314
|
},
|
|
309
315
|
async runProjectBriefRefresh(input, context) {
|
|
310
|
-
const
|
|
316
|
+
const { communication_language: language, ...businessInput } = input;
|
|
317
|
+
const instructions = renderLanguageAwarePrompt({
|
|
311
318
|
templateKey: "procedures.project_brief_refresh",
|
|
312
319
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
313
320
|
variables: {
|
|
314
|
-
workflow_input_json:
|
|
321
|
+
workflow_input_json: businessInput,
|
|
315
322
|
},
|
|
316
|
-
});
|
|
323
|
+
}, language);
|
|
317
324
|
const result = await runOpenAiStructuredOutput({
|
|
318
325
|
client: options.client,
|
|
319
326
|
model: options.config.default_model,
|
|
@@ -331,22 +338,24 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
331
338
|
return result.output;
|
|
332
339
|
},
|
|
333
340
|
async runTaskCompile(input, context) {
|
|
334
|
-
const
|
|
341
|
+
const language = input.communication_language;
|
|
342
|
+
const contract = languageOutputContract(TASK_COMPILE_OUTPUT_SCHEMA, isTaskCompileStructuredOutput, language);
|
|
343
|
+
const instructions = renderLanguageAwarePrompt({
|
|
335
344
|
templateKey: "procedures.task_compile",
|
|
336
345
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
337
346
|
variables: {
|
|
338
347
|
workflow_input_json: buildTaskCompilePromptInput(input),
|
|
339
348
|
},
|
|
340
|
-
});
|
|
349
|
+
}, language, true);
|
|
341
350
|
const result = await runDurableReadOnlyProcedure({
|
|
342
351
|
options,
|
|
343
352
|
context,
|
|
344
353
|
kind: "task_compile",
|
|
345
|
-
archiveAfterTurn: (output) => "proposal" in output.result,
|
|
354
|
+
archiveAfterTurn: (output) => "proposal" in contract.unwrap(output).output.result,
|
|
346
355
|
invocation: {
|
|
347
|
-
...readOnlyAppServerOptions(options, instructions,
|
|
356
|
+
...readOnlyAppServerOptions(options, instructions, contract.schema, "task_compile"),
|
|
348
357
|
...readOnlyRuntimeTelemetry(context, "task_compile"),
|
|
349
|
-
validateOutput:
|
|
358
|
+
validateOutput: contract.validate,
|
|
350
359
|
networkAccess: false,
|
|
351
360
|
webSearchMode: "disabled",
|
|
352
361
|
},
|
|
@@ -355,16 +364,22 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
355
364
|
workflow_ref: context?.workflow_ref ?? input.workflow_ref,
|
|
356
365
|
...(context?.activity_ref === undefined ? {} : { activity_ref: context.activity_ref }),
|
|
357
366
|
});
|
|
358
|
-
|
|
367
|
+
const decoded = contract.unwrap(result.output);
|
|
368
|
+
return {
|
|
369
|
+
...taskCompileWorkflowOutput(decoded.output),
|
|
370
|
+
...(decoded.language === undefined ? {} : { communication_language: decoded.language }),
|
|
371
|
+
};
|
|
359
372
|
},
|
|
360
373
|
async runFollowUpCheck(input, context) {
|
|
361
|
-
const
|
|
374
|
+
const language = input.communication_language;
|
|
375
|
+
const contract = languageOutputContract(FOLLOW_UP_CHECK_OUTPUT_SCHEMA, isFollowUpCheckStructuredOutput, language);
|
|
376
|
+
const instructions = renderLanguageAwarePrompt({
|
|
362
377
|
templateKey: "procedures.follow_up_check",
|
|
363
378
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
364
379
|
variables: {
|
|
365
380
|
workflow_input_json: followUpCheckPromptInput(input),
|
|
366
381
|
},
|
|
367
|
-
});
|
|
382
|
+
}, language, true);
|
|
368
383
|
const result = await runOpenAiStructuredOutput({
|
|
369
384
|
client: options.client,
|
|
370
385
|
model: options.config.default_model,
|
|
@@ -372,8 +387,8 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
372
387
|
input: "Run follow_up_check and return only structured JSON.",
|
|
373
388
|
schemaName: "follow_up_check_output",
|
|
374
389
|
schemaDescription: "Tutti follow_up_check terminal workflow output.",
|
|
375
|
-
schema:
|
|
376
|
-
validate:
|
|
390
|
+
schema: contract.schema,
|
|
391
|
+
validate: contract.validate,
|
|
377
392
|
});
|
|
378
393
|
recordUsage(options, "follow_up_check", result, {
|
|
379
394
|
workflow_ref: context?.workflow_ref ?? input.workflow_ref,
|
|
@@ -381,18 +396,23 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
381
396
|
task_id: input.task_id,
|
|
382
397
|
run_lineage_kind: input.run_lineage.kind,
|
|
383
398
|
});
|
|
384
|
-
|
|
399
|
+
const decoded = contract.unwrap(result.output);
|
|
400
|
+
return {
|
|
401
|
+
...followUpCheckWorkflowOutput(decoded.output),
|
|
402
|
+
...(decoded.language === undefined ? {} : { communication_language: decoded.language }),
|
|
403
|
+
};
|
|
385
404
|
},
|
|
386
405
|
};
|
|
387
406
|
if (options.readOnlyAppServer !== undefined) {
|
|
388
407
|
runner.runProjectContextBootstrap = async (input, context) => {
|
|
389
|
-
const
|
|
408
|
+
const { communication_language: language, ...businessInput } = input;
|
|
409
|
+
const instructions = renderLanguageAwarePrompt({
|
|
390
410
|
templateKey: "procedures.project_context_bootstrap",
|
|
391
411
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
392
412
|
variables: {
|
|
393
|
-
workflow_input_json:
|
|
413
|
+
workflow_input_json: businessInput,
|
|
394
414
|
},
|
|
395
|
-
});
|
|
415
|
+
}, language);
|
|
396
416
|
const result = await runDurableReadOnlyProcedure({
|
|
397
417
|
options,
|
|
398
418
|
context,
|
|
@@ -411,10 +431,10 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
411
431
|
return result.output;
|
|
412
432
|
};
|
|
413
433
|
runner.runContextSync = async (input, context) => {
|
|
414
|
-
const instructions =
|
|
434
|
+
const instructions = renderLanguageAwarePrompt({
|
|
415
435
|
templateKey: "procedures.context_sync",
|
|
416
436
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
417
|
-
});
|
|
437
|
+
}, input.communication_language);
|
|
418
438
|
const result = await runDurableReadOnlyProcedure({
|
|
419
439
|
options,
|
|
420
440
|
context,
|
|
@@ -434,10 +454,10 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
434
454
|
};
|
|
435
455
|
runner.runReferenceFileSummary = async (input, context) => {
|
|
436
456
|
const sourcePath = referenceSummarySourcePath(options, input);
|
|
437
|
-
const instructions =
|
|
457
|
+
const instructions = renderLanguageAwarePrompt({
|
|
438
458
|
templateKey: "procedures.reference_file_summary",
|
|
439
459
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
440
|
-
});
|
|
460
|
+
}, input.communication_language);
|
|
441
461
|
const workspace = createReferenceSummaryWorkspace({
|
|
442
462
|
sourcePath,
|
|
443
463
|
originalPath: input.file.path,
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { ExecutionRuntimeSnapshot, MessageProjection, RunResultProjection, TaskDetailProjection, WorklistProjection } from "@tutti/shared/schemas/api";
|
|
2
2
|
import type { RecentReferenceContext } from "../reference-context-types.js";
|
|
3
|
+
import type { CommunicationLanguageContext, LanguageAwareOutput } from "../../communication-language/index.js";
|
|
4
|
+
type LanguageAwareInput = {
|
|
5
|
+
communication_language?: CommunicationLanguageContext;
|
|
6
|
+
};
|
|
3
7
|
import type { PromptSourceMessage, TaskCompileClarificationContext } from "../task-source-context-types.js";
|
|
4
8
|
import type { ClarificationRequestPayload, TaskContractProjection } from "@tutti/shared/schemas/api";
|
|
5
9
|
import type { ProjectDocKey } from "@tutti/shared/schemas/api";
|
|
6
10
|
import type { ActivityRef, ClarificationRoundRef, ClarificationThreadRef, MessageId, TaskId, TaskModuleId, WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
7
11
|
import type { RunLineage } from "@tutti/shared/domain";
|
|
8
12
|
import type { ProjectBriefSnapshot, ProjectBriefSourceDocument } from "../../project-brief/index.js";
|
|
9
|
-
export type ScratchpadRefreshWorkflowInput = {
|
|
13
|
+
export type ScratchpadRefreshWorkflowInput = LanguageAwareInput & {
|
|
10
14
|
project_brief?: ProjectBriefSnapshot;
|
|
11
15
|
worklist: ScratchpadRefreshWorklistInput;
|
|
12
16
|
active_task_compile?: ScratchpadWorkflowSnapshot;
|
|
@@ -43,7 +47,7 @@ export type ProcedureWorkflowRunContext = {
|
|
|
43
47
|
runtime?: ExecutionRuntimeSnapshot;
|
|
44
48
|
}) => void;
|
|
45
49
|
};
|
|
46
|
-
export type ScratchpadRefreshWorkflowOutput = {
|
|
50
|
+
export type ScratchpadRefreshWorkflowOutput = LanguageAwareOutput & ({
|
|
47
51
|
decision: "ready";
|
|
48
52
|
scratchpad_snapshot: {
|
|
49
53
|
topic: string;
|
|
@@ -58,7 +62,7 @@ export type ScratchpadRefreshWorkflowOutput = {
|
|
|
58
62
|
summary: string;
|
|
59
63
|
request: string;
|
|
60
64
|
};
|
|
61
|
-
};
|
|
65
|
+
});
|
|
62
66
|
export type TaskCompileProposal = {
|
|
63
67
|
modules: TaskCompileProposalModule[];
|
|
64
68
|
tasks: TaskCompileProposalTask[];
|
|
@@ -74,7 +78,7 @@ export type TaskCompileProposalTask = {
|
|
|
74
78
|
summary: string;
|
|
75
79
|
contract: TaskContractProjection;
|
|
76
80
|
};
|
|
77
|
-
export type TaskCompileWorkflowInput = {
|
|
81
|
+
export type TaskCompileWorkflowInput = LanguageAwareInput & {
|
|
78
82
|
workflow_ref: WorkflowInvocationRef;
|
|
79
83
|
scratchpad: ScratchpadWorkflowSnapshot;
|
|
80
84
|
source_messages: PromptSourceMessage[];
|
|
@@ -82,13 +86,13 @@ export type TaskCompileWorkflowInput = {
|
|
|
82
86
|
recent_references?: RecentReferenceContext[];
|
|
83
87
|
clarification_rounds?: TaskCompileClarificationContext[];
|
|
84
88
|
};
|
|
85
|
-
export type TaskCompileWorkflowOutput = {
|
|
89
|
+
export type TaskCompileWorkflowOutput = LanguageAwareOutput & ({
|
|
86
90
|
decision: "ready";
|
|
87
91
|
proposal: TaskCompileProposal;
|
|
88
92
|
} | {
|
|
89
93
|
decision: "needs_human";
|
|
90
94
|
clarification_request_payload: ClarificationRequestPayload;
|
|
91
|
-
};
|
|
95
|
+
});
|
|
92
96
|
export type TaskCompilePromptInput = {
|
|
93
97
|
scratchpad: {
|
|
94
98
|
topic: string;
|
|
@@ -145,7 +149,7 @@ export type TaskCompileStructuredProposalTask = {
|
|
|
145
149
|
goal: string;
|
|
146
150
|
scope: string[];
|
|
147
151
|
};
|
|
148
|
-
export type ProjectContextBootstrapWorkflowInput = {
|
|
152
|
+
export type ProjectContextBootstrapWorkflowInput = LanguageAwareInput & {
|
|
149
153
|
project_name: string;
|
|
150
154
|
missing_docs?: ProjectContextBootstrapMissingDoc[];
|
|
151
155
|
scratchpad?: {
|
|
@@ -178,7 +182,7 @@ export type ContextSyncWorkflowTrigger = {
|
|
|
178
182
|
completed_task_count: number;
|
|
179
183
|
module_count: number;
|
|
180
184
|
};
|
|
181
|
-
export type ContextSyncWorkflowInput = {
|
|
185
|
+
export type ContextSyncWorkflowInput = LanguageAwareInput & {
|
|
182
186
|
workflow_ref: WorkflowInvocationRef;
|
|
183
187
|
activity_ref: ActivityRef;
|
|
184
188
|
trigger: ContextSyncWorkflowTrigger;
|
|
@@ -187,11 +191,11 @@ export type ContextSyncWorkflowOutput = {
|
|
|
187
191
|
summary: string;
|
|
188
192
|
updates: ContextSyncDocumentUpdate[];
|
|
189
193
|
};
|
|
190
|
-
export type ProjectBriefRefreshWorkflowInput = {
|
|
194
|
+
export type ProjectBriefRefreshWorkflowInput = LanguageAwareInput & {
|
|
191
195
|
docs: ProjectBriefSourceDocument[];
|
|
192
196
|
};
|
|
193
197
|
export type ProjectBriefRefreshWorkflowOutput = ProjectBriefSnapshot;
|
|
194
|
-
export type ReferenceFileSummaryWorkflowInput = {
|
|
198
|
+
export type ReferenceFileSummaryWorkflowInput = LanguageAwareInput & {
|
|
195
199
|
workflow_ref: WorkflowInvocationRef;
|
|
196
200
|
activity_ref: ActivityRef;
|
|
197
201
|
file: {
|
|
@@ -225,7 +229,7 @@ export type ReferenceFileSummaryStructuredOutput = {
|
|
|
225
229
|
};
|
|
226
230
|
};
|
|
227
231
|
};
|
|
228
|
-
export type FollowUpCheckWorkflowInput = {
|
|
232
|
+
export type FollowUpCheckWorkflowInput = LanguageAwareInput & {
|
|
229
233
|
workflow_ref: WorkflowInvocationRef;
|
|
230
234
|
task_id: TaskId;
|
|
231
235
|
task_detail: TaskDetailProjection;
|
|
@@ -237,7 +241,7 @@ export type FollowUpCheckWorkflowInput = {
|
|
|
237
241
|
latest_run_result: RunResultProjection;
|
|
238
242
|
run_lineage: RunLineage;
|
|
239
243
|
};
|
|
240
|
-
export type FollowUpCheckWorkflowOutput = {
|
|
244
|
+
export type FollowUpCheckWorkflowOutput = LanguageAwareOutput & ({
|
|
241
245
|
decision: "resume";
|
|
242
246
|
summary: string;
|
|
243
247
|
} | {
|
|
@@ -247,7 +251,7 @@ export type FollowUpCheckWorkflowOutput = {
|
|
|
247
251
|
} | {
|
|
248
252
|
decision: "requires_retasking";
|
|
249
253
|
summary: string;
|
|
250
|
-
};
|
|
254
|
+
});
|
|
251
255
|
export type FollowUpCheckStructuredOutput = {
|
|
252
256
|
result: {
|
|
253
257
|
resume: {
|
|
@@ -281,4 +285,5 @@ export type ProcedureWorkflowRunnerResolution = {
|
|
|
281
285
|
retryable: boolean;
|
|
282
286
|
};
|
|
283
287
|
export type ProcedureWorkflowRunnerResolver = () => ProcedureWorkflowRunnerResolution;
|
|
288
|
+
export {};
|
|
284
289
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type PromptTemplateKey = "procedures.project_context_bootstrap" | "procedures.context_sync" | "procedures.project_brief_refresh" | "procedures.scratchpad_refresh" | "procedures.task_compile" | "procedures.reference_file_summary" | "procedures.follow_up_check" | "runs.task_execute" | "runs.task_finalize" | "runs.task_recovery" | "runs.task_result_contract" | "artifacts.applicability" | "chat.assistant" | "codex.no_write_smoke";
|
|
1
|
+
export type PromptTemplateKey = "communication_language" | "communication_language_result" | "procedures.project_context_bootstrap" | "procedures.context_sync" | "procedures.project_brief_refresh" | "procedures.scratchpad_refresh" | "procedures.task_compile" | "procedures.reference_file_summary" | "procedures.follow_up_check" | "runs.task_execute" | "runs.task_finalize" | "runs.task_recovery" | "runs.task_result_contract" | "artifacts.applicability" | "chat.assistant" | "codex.no_write_smoke";
|
|
2
2
|
export type RenderPromptTemplateOptions = {
|
|
3
3
|
templateKey: PromptTemplateKey;
|
|
4
4
|
variables?: Record<string, unknown>;
|
|
@@ -12,6 +12,8 @@ export class PromptTemplateError extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
const defaultPromptsRoot = fileURLToPath(new URL("../../prompts", import.meta.url));
|
|
14
14
|
const TEMPLATE_REGISTRY = {
|
|
15
|
+
communication_language: "communication-language.md",
|
|
16
|
+
communication_language_result: "communication-language-result.md",
|
|
15
17
|
"procedures.project_context_bootstrap": "procedures/project-context-bootstrap.md",
|
|
16
18
|
"procedures.context_sync": "procedures/context-sync.md",
|
|
17
19
|
"procedures.project_brief_refresh": "procedures/project-brief-refresh.md",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { openAiCredentialAccess } from "../providers/openai/execution-access.js";
|
|
2
2
|
import { renderPromptTemplate } from "../prompt-templates/index.js";
|
|
3
|
+
import { renderLanguageAwarePrompt } from "../communication-language/prompt.js";
|
|
3
4
|
import { CODEX_APP_SERVER_VERSION } from "../providers/openai/codex-app-server.js";
|
|
4
5
|
import { CodexAppServerWorkspaceWriteRunError, runCodexAppServerWorkspaceWriteRun, } from "../providers/openai/app-server/workspace-write-run.js";
|
|
5
6
|
import { acquireCodexTaskSessionLock, createProviderFingerprint, markCodexTaskSessionArchived, openCodexTaskSession, readCodexSessionRecoveryEvidence, recordCodexSessionArchiveFailure, recordCodexTaskSessionThread, writeCodexSessionRecoveryEvidence, } from "../providers/openai/app-server/session-store.js";
|
|
@@ -55,24 +56,26 @@ function createExecutePrompt(options, input, session) {
|
|
|
55
56
|
else {
|
|
56
57
|
executionInput = taskContractRunInput(input);
|
|
57
58
|
}
|
|
58
|
-
return
|
|
59
|
+
return renderLanguageAwarePrompt({
|
|
59
60
|
templateKey: "runs.task_execute",
|
|
60
61
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
61
62
|
variables: { execution_input_json: executionInput },
|
|
62
|
-
});
|
|
63
|
+
}, input.communication_language);
|
|
63
64
|
}
|
|
64
|
-
function createFinalizePrompt(options) {
|
|
65
|
-
return
|
|
65
|
+
function createFinalizePrompt(options, input) {
|
|
66
|
+
return renderLanguageAwarePrompt({
|
|
66
67
|
templateKey: "runs.task_finalize",
|
|
67
68
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
68
69
|
variables: { result_contract: renderResultContract(options) },
|
|
69
|
-
});
|
|
70
|
+
}, input.communication_language);
|
|
70
71
|
}
|
|
71
72
|
function createRecoveryPrompt(input) {
|
|
72
73
|
const needsCanonicalContext = input.session === undefined || input.session.metadata.thread_id === undefined;
|
|
73
|
-
return
|
|
74
|
+
return renderLanguageAwarePrompt({
|
|
74
75
|
templateKey: "runs.task_recovery",
|
|
75
|
-
...(input.options.promptsRoot === undefined
|
|
76
|
+
...(input.options.promptsRoot === undefined
|
|
77
|
+
? {}
|
|
78
|
+
: { promptsRoot: input.options.promptsRoot }),
|
|
76
79
|
variables: {
|
|
77
80
|
recovery_input_json: {
|
|
78
81
|
...(needsCanonicalContext
|
|
@@ -82,7 +85,7 @@ function createRecoveryPrompt(input) {
|
|
|
82
85
|
},
|
|
83
86
|
result_contract: renderResultContract(input.options),
|
|
84
87
|
},
|
|
85
|
-
});
|
|
88
|
+
}, input.pipelineInput.communication_language);
|
|
86
89
|
}
|
|
87
90
|
function usageSource(input, phase) {
|
|
88
91
|
if (phase === "finalize") {
|
|
@@ -372,7 +375,7 @@ export async function runWorkspaceWriteTask(options, input) {
|
|
|
372
375
|
structuredResult = await runTaskTurn({
|
|
373
376
|
options,
|
|
374
377
|
pipelineInput: input,
|
|
375
|
-
prompt: createFinalizePrompt(options),
|
|
378
|
+
prompt: createFinalizePrompt(options, input),
|
|
376
379
|
phase: "finalize",
|
|
377
380
|
sandboxMode: "read-only",
|
|
378
381
|
networkAccess: false,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE TABLE communication_language_state (
|
|
2
|
+
owner_kind TEXT NOT NULL CHECK (owner_kind IN ('project', 'scratchpad', 'workflow', 'task')),
|
|
3
|
+
owner_ref TEXT NOT NULL CHECK (length(owner_ref) BETWEEN 1 AND 128),
|
|
4
|
+
locale TEXT NOT NULL CHECK (length(locale) BETWEEN 2 AND 20),
|
|
5
|
+
preference TEXT NOT NULL CHECK (preference IN ('auto', 'fixed')),
|
|
6
|
+
basis TEXT NOT NULL CHECK (basis IN ('discussion', 'explicit', 'inherited', 'default')),
|
|
7
|
+
policy_version INTEGER NOT NULL CHECK (policy_version = 1),
|
|
8
|
+
activity_ref TEXT,
|
|
9
|
+
source_message_id TEXT,
|
|
10
|
+
source_created_at TEXT,
|
|
11
|
+
updated_at TEXT NOT NULL,
|
|
12
|
+
PRIMARY KEY (owner_kind, owner_ref),
|
|
13
|
+
CHECK ((source_message_id IS NULL) = (source_created_at IS NULL))
|
|
14
|
+
);
|
package/package.json
CHANGED
package/prompts/README.md
CHANGED
|
@@ -13,6 +13,7 @@ Prompt / skill 改造后的 live 实验计划与记录见 [prompt-flow-experimen
|
|
|
13
13
|
|
|
14
14
|
## 结构
|
|
15
15
|
|
|
16
|
+
- `communication-language.md`/`communication-language-result.md`:跨流程协作语言规则与内部 provider envelope;区分任务说明、交付物与已有文档语言,见[系统规范](../../../docs/system/communication-language.md)。
|
|
16
17
|
- `procedures/`:`scratchpad_refresh`、`project_brief_refresh`、`task_compile`、`project_context_bootstrap`、`context_sync`、`reference_summary_refresh`、`follow_up_check` 等 Procedure / workflow prompt。
|
|
17
18
|
- `artifacts/`:候选实现完成后的 transient Artifact applicability 判断;只接收 bounded task / diff / repo evidence,不写回 Task contract 或 repo。
|
|
18
19
|
- `runs/`:正式 task `Run`、task-bound continuation 与 pipeline self-correction retry 等 Run pipeline prompt;task contract 可附带 receipt-derived `source_messages`、已完成 Task Compile `clarification_rounds` 与 compact `recent_references`,两类 retry 都保留它们。provider transient retry 不新增 prompt,而是复用失败 attempt 的同一 prompt family。所有 Run prompt都以持久 project workspace为 cwd contract,不设计 promotion reconcile prompt。
|
|
@@ -8,7 +8,7 @@ model_path: codex.app_server.read_only
|
|
|
8
8
|
|
|
9
9
|
You are Tutti, a read-only project Q&A assistant participating in Tutti collaboration chat.
|
|
10
10
|
|
|
11
|
-
Answer the explicit `@tutti` question concisely,
|
|
11
|
+
Answer the explicit `@tutti` question concisely, following the communication-language policy when supplied; otherwise use the user's language. Use the supplied context for ordinary discussion; use attached read-only skills when the answer requires additional evidence.
|
|
12
12
|
|
|
13
13
|
# Instructions
|
|
14
14
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
template_key: communication_language_result
|
|
3
|
+
owner: communication-language
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
## Language result envelope
|
|
7
|
+
|
|
8
|
+
The following workflow's entire business JSON belongs under `output`. Return exactly two
|
|
9
|
+
root fields: `communication_language` and `output`. Its examples describe `output`, not the
|
|
10
|
+
outer envelope. Do not put language metadata in summaries, answers, task scope or file content.
|
|
11
|
+
|
|
12
|
+
`communication_language` has exactly four required fields:
|
|
13
|
+
|
|
14
|
+
- `locale`: the canonical locale used for the human-facing prose.
|
|
15
|
+
- `preference`: `auto` or `fixed`. Preserve inherited preference unless an explicit request
|
|
16
|
+
changes it. Automatic inference uses `auto`.
|
|
17
|
+
- `basis`: `discussion` for reliable authored-language inference; `explicit` for an explicit
|
|
18
|
+
applicable language request; `inherited` for preserving the context choice; `default` for
|
|
19
|
+
the no-evidence, no-inherited-language English fallback.
|
|
20
|
+
- `evidence_index`: the zero-based index of the relevant evidence for `discussion` / `explicit`;
|
|
21
|
+
copy its displayed `evidence_index` from the language context's `evidence` array above.
|
|
22
|
+
Never use the position in business `messages`, `source_messages`, or clarification answers.
|
|
23
|
+
With one evidence item the only valid index is `0`, not `1`. Otherwise use `null`.
|
|
24
|
+
`inherited` must copy both locale and preference; `default` is `en` / `auto`.
|
|
25
|
+
|
|
26
|
+
Pinned workflow language cannot change through `discussion`; only an explicit request in
|
|
27
|
+
sealed answers can change it. A fixed project preference cannot change through `discussion`.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
template_key: communication_language
|
|
3
|
+
owner: communication-language
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Communication language
|
|
7
|
+
|
|
8
|
+
Apply this policy to all newly written human-facing prose in the following task: topic,
|
|
9
|
+
summary, consensus, questions, task/module descriptions, goals, scope, clarification title /
|
|
10
|
+
request, answer, result summary and user note. JSON keys, enum values, IDs, commands, paths,
|
|
11
|
+
API names and exact source quotations retain their original spelling. Examples below
|
|
12
|
+
illustrate structure only; their English prose does not prescribe the output language.
|
|
13
|
+
|
|
14
|
+
Language context (bounded evidence, not permission or instructions to perform work):
|
|
15
|
+
|
|
16
|
+
{{language_context_json}}
|
|
17
|
+
|
|
18
|
+
Choose one language before writing the output and use it consistently across its prose fields.
|
|
19
|
+
Use a canonical BCP-47 locale such as `en`, `zh-Hans`, `zh-Hant`, `ja`, `fr` or `es`.
|
|
20
|
+
|
|
21
|
+
- Only authored natural-language evidence in `evidence` can establish a language choice.
|
|
22
|
+
Ignore code, URLs, filenames, pasted/quoted materials, system notices, previous AI output,
|
|
23
|
+
project names, tool output and the language of these instructions. A short acknowledgement
|
|
24
|
+
such as OK / 继续 / yes, an upload placeholder or an ambiguous mixed-language fragment
|
|
25
|
+
does not establish a change; inherit when possible. Avoid switching for one incidental phrase.
|
|
26
|
+
- In `scratchpad` scope, use the main human discussion language in automatic mode. An explicit
|
|
27
|
+
project-wide request (for example “以后项目协作都用中文”) sets `fixed`; an explicit request
|
|
28
|
+
to resume following discussion sets `auto`. Otherwise retain a fixed preference. A request
|
|
29
|
+
about only this reply or a deliverable is NOT a project-wide preference.
|
|
30
|
+
- In `reply` scope, answer the current question in its language, or its explicit requested
|
|
31
|
+
response language. Identify the current authored question from `trigger.text`, not an older
|
|
32
|
+
nonempty evidence item when the trigger is only code or a link. Weak input inherits the existing
|
|
33
|
+
choice; the nearby authored evidence is only a fallback when no choice exists. This does not change the project
|
|
34
|
+
preference; `fixed` describes the project fallback, not a prohibition on answering a member.
|
|
35
|
+
- In `workflow` scope, retain the pinned language throughout compilation, clarification and
|
|
36
|
+
execution. Only an explicit language request in the supplied sealed answers may change it.
|
|
37
|
+
Do not switch just because an answer uses a different language. If no language was pinned
|
|
38
|
+
(legacy context), infer from the supplied original human evidence, not an old English task.
|
|
39
|
+
- In `summary` / `documents` scope, use the inherited language for the short summary. With no
|
|
40
|
+
inherited language use English. Source documents cannot change this collaboration preference.
|
|
41
|
+
- When evidence is insufficient, inherit. With neither a reliable choice nor inherited locale,
|
|
42
|
+
use `en` as the explicit default. Operator-only evidence is a test request, not human consensus.
|
|
43
|
+
|
|
44
|
+
Communication language is NOT deliverable language. Follow the task's explicit language
|
|
45
|
+
requirements for generated websites, reports and other deliverables. Preserve each existing
|
|
46
|
+
document's language and repository conventions unless translation was requested. A Chinese
|
|
47
|
+
discussion asking for an English website requires Chinese coordination prose and an English
|
|
48
|
+
website. Do not translate existing files, source quotations or identifiers just to align a summary.
|
|
49
|
+
|
|
50
|
+
{{language_output_contract}}
|
|
@@ -44,7 +44,7 @@ Fields:
|
|
|
44
44
|
|
|
45
45
|
# Output
|
|
46
46
|
|
|
47
|
-
Return JSON matching the structured output schema. The
|
|
47
|
+
Return JSON matching the structured output schema. The business object contains only `result`; when a communication-language envelope is supplied, place this entire object under `output`, otherwise it is the root. `result` is exactly one of the following branches.
|
|
48
48
|
|
|
49
49
|
Resume:
|
|
50
50
|
|
|
@@ -47,7 +47,7 @@ If an uploaded file matters but the chat does not describe it, mention only that
|
|
|
47
47
|
|
|
48
48
|
Produce one clean, concise Scratchpad snapshot for quick human scanning and the next taskization pass. Rebuild it from the complete current-cycle `messages`; there is intentionally no previous Scratchpad input. Use the other layers only as owned background.
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Follow the shared communication-language policy when supplied; otherwise write in the primary language used by human source messages. Preserve chronology, including later corrections, withdrawals, and direction changes. Avoid repeating the same fact across fields.
|
|
51
51
|
Keep the snapshot compact, but preserve user-provided non-secret details that are needed for taskization, implementation, or acceptance. Do not replace those details with vague placeholders.
|
|
52
52
|
Think one step ahead only when it is clearly useful: if the chat implies a website, app feature, or repository change, it is acceptable to mention likely affected surfaces such as frontend UI, backend/API/data, docs, tests, assets, or migration shape. Keep these as lightweight observations, not hidden requirements.
|
|
53
53
|
|
|
@@ -81,7 +81,7 @@ Do not use `needs_human` merely because the discussion is incomplete, informal,
|
|
|
81
81
|
|
|
82
82
|
## Output
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
The business object has exactly one key: `result`. When a communication-language envelope is supplied, place this entire object under `output`; otherwise it is the root. Branches are mutually exclusive:
|
|
85
85
|
|
|
86
86
|
- `ready`: include only `decision` and `scratchpad_snapshot`; do not include `request_payload`.
|
|
87
87
|
- `needs_human`: include only `decision` and `request_payload`; do not include `scratchpad_snapshot`.
|
|
@@ -85,7 +85,7 @@ Avoid repeating the same idea across `title`, `goal`, and `scope`. Keep the task
|
|
|
85
85
|
|
|
86
86
|
# Output
|
|
87
87
|
|
|
88
|
-
Return JSON matching the structured output schema. The
|
|
88
|
+
Return JSON matching the structured output schema. The business object contains only `result`; when a communication-language envelope is supplied, place this entire object under `output`, otherwise it is the root. `result` is exactly one of the following branches.
|
|
89
89
|
|
|
90
90
|
Ready example:
|
|
91
91
|
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
## 当前背景
|
|
8
8
|
|
|
9
|
+
跨流程语言前缀统一见 [communication-language.md](./communication-language.md)。Scratchpad/Task Compile/Follow-up 的实际 provider 输出增加外层 `{ communication_language, output }`,下文各自业务 JSON 形状位于 `output`;其他模型流程仅增加语言上下文提示。共享规则不改变冻结来源、skill selection、文档权限或历史正文,详见[系统规范](../../../docs/system/communication-language.md)。
|
|
10
|
+
|
|
9
11
|
模型调用当前分成三类:
|
|
10
12
|
|
|
11
13
|
- OpenAI SDK structured output:用于轻量结构化整理和判断。调用统一经过 Responses API strict JSON schema,schema 由 TypeScript 代码绑定,prompt 只能影响内容倾向,不能新增输出字段。
|