@xfey/tutti 0.1.127 → 0.1.129

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 (85) hide show
  1. package/dist/approvals/decision-command.d.ts +2 -2
  2. package/dist/chat-assistant/diagnostics.d.ts +17 -3
  3. package/dist/chat-assistant/diagnostics.js +5 -2
  4. package/dist/chat-assistant/failure-messages.d.ts +4 -0
  5. package/dist/chat-assistant/failure-messages.js +57 -0
  6. package/dist/chat-assistant/failures.d.ts +27 -0
  7. package/dist/chat-assistant/failures.js +46 -0
  8. package/dist/chat-assistant/index.d.ts +18 -4
  9. package/dist/chat-assistant/index.js +254 -51
  10. package/dist/chat-assistant/language-context.d.ts +2 -0
  11. package/dist/chat-assistant/language-context.js +17 -14
  12. package/dist/chat-assistant/requests.d.ts +34 -0
  13. package/dist/chat-assistant/requests.js +64 -0
  14. package/dist/collaboration-ingestion/clarification.js +3 -1
  15. package/dist/collaboration-ingestion/main-chat.js +1 -0
  16. package/dist/collaboration-ingestion/types.d.ts +2 -0
  17. package/dist/collaboration-state/clarification-snapshot.d.ts +5 -5
  18. package/dist/collaboration-state/context-sync-attempts.d.ts +9 -0
  19. package/dist/collaboration-state/context-sync-attempts.js +13 -0
  20. package/dist/collaboration-state/task-compile-context.d.ts +1 -1
  21. package/dist/collaboration-state/task-compile-context.js +11 -1
  22. package/dist/collaboration-state/task-compile-requests.d.ts +6 -0
  23. package/dist/collaboration-state/task-compile-requests.js +16 -0
  24. package/dist/communication-language/notice-locale.d.ts +4 -0
  25. package/dist/communication-language/notice-locale.js +14 -0
  26. package/dist/control-plane/context-sync-completion.d.ts +7 -0
  27. package/dist/control-plane/context-sync-completion.js +27 -0
  28. package/dist/control-plane/context-sync.d.ts +1 -0
  29. package/dist/control-plane/context-sync.js +23 -0
  30. package/dist/control-plane/index.d.ts +13 -4
  31. package/dist/control-plane/index.js +30 -23
  32. package/dist/control-plane/task-compile-continuation.js +2 -0
  33. package/dist/control-plane/task-compile-request-status.d.ts +6 -0
  34. package/dist/control-plane/task-compile-request-status.js +70 -0
  35. package/dist/control-plane/task-compile-start.js +40 -2
  36. package/dist/control-plane/types.d.ts +2 -0
  37. package/dist/providers/failure-classification.d.ts +23 -0
  38. package/dist/providers/failure-classification.js +43 -0
  39. package/dist/providers/invocation-progress.d.ts +6 -0
  40. package/dist/providers/invocation-progress.js +24 -0
  41. package/dist/providers/openai/app-server/read-only-procedure.js +1 -0
  42. package/dist/providers/openai/chat-assistant.js +2 -1
  43. package/dist/reference-access/read-evidence.d.ts +2 -0
  44. package/dist/reference-access/read-evidence.js +5 -0
  45. package/dist/reference-access/service.d.ts +2 -0
  46. package/dist/reference-access/service.js +2 -0
  47. package/dist/runtime-failures.js +15 -1
  48. package/dist/server-shell/cli/external-reference-runtime.js +6 -3
  49. package/dist/server-shell/cli/host-server-runtime.js +8 -2
  50. package/dist/server-shell/cli/relay-registration.js +1 -0
  51. package/dist/server-shell/http/routes/project-api/messages-routes.js +22 -1
  52. package/dist/server-shell/http/routes/project-api/openapi-collaboration-routes.d.ts +140 -5
  53. package/dist/server-shell/http/routes/project-api/openapi-collaboration-routes.js +29 -2
  54. package/dist/server-shell/http/routes/project-api/openapi-skills-routes.d.ts +2 -0
  55. package/dist/server-shell/http/routes/project-api/openapi-workspace-routes.d.ts +6 -0
  56. package/dist/server-shell/http/routes/project-api/openapi.d.ts +148 -5
  57. package/dist/server-shell/http/routes/project-api/schemas.d.ts +6 -0
  58. package/dist/server-shell/http/routes/project-api/schemas.js +1 -0
  59. package/dist/server-shell/http/routes/project-api/types.d.ts +1 -0
  60. package/dist/server-shell/http/routes/project-api/workflow-routes.js +39 -3
  61. package/dist/server-shell/http/routes/project-api/workspace-projections.js +1 -0
  62. package/dist/server-shell/http/validation.js +8 -2
  63. package/dist/server-shell/local-console/managed-project-service.d.ts +1 -1
  64. package/dist/server-shell/managed-access/transport.d.ts +1 -1
  65. package/migrations/0024_chat_requests.sql +19 -0
  66. package/migrations/0025_task_compile_requests.sql +50 -0
  67. package/migrations/0026_context_sync_and_chat_locale.sql +12 -0
  68. package/migrations/README.md +3 -1
  69. package/node_modules/@tutti/relay-client/dist/host-control.d.ts +1 -0
  70. package/node_modules/@tutti/relay-client/dist/host-control.js +1 -0
  71. package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +1 -0
  72. package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -0
  73. package/node_modules/@tutti/shared/dist/schemas/api/operation-status.d.ts +174 -0
  74. package/node_modules/@tutti/shared/dist/schemas/api/operation-status.js +75 -0
  75. package/node_modules/@tutti/shared/dist/schemas/api/primitives.d.ts +1 -0
  76. package/node_modules/@tutti/shared/dist/schemas/api/primitives.js +1 -0
  77. package/node_modules/@tutti/shared/dist/schemas/api/workspace-commands.d.ts +1 -0
  78. package/node_modules/@tutti/shared/dist/schemas/api/workspace-commands.js +2 -1
  79. package/package.json +1 -1
  80. package/web/assets/{homepage-motion-scene-DyEmWwvt.js → homepage-motion-scene-BHhw4CfM.js} +1 -1
  81. package/web/assets/index-5COc1Yku.js +70 -0
  82. package/web/assets/index-BJvKuUiT.css +1 -0
  83. package/web/index.html +2 -2
  84. package/web/assets/index-By3idT4U.js +0 -70
  85. package/web/assets/index-DSBjOZmJ.css +0 -1
@@ -25,8 +25,8 @@ export declare function executeApprovalDecisionCommand(input: {
25
25
  state: "pending";
26
26
  request: {
27
27
  expires_at?: string;
28
- task_id?: string;
29
28
  activity_ref?: string;
29
+ task_id?: string;
30
30
  reason?: string;
31
31
  file_change?: {
32
32
  paths?: string[];
@@ -69,8 +69,8 @@ export declare function executeApprovalDecisionCommand(input: {
69
69
  state: "resolved";
70
70
  request: {
71
71
  expires_at?: string;
72
- task_id?: string;
73
72
  activity_ref?: string;
73
+ task_id?: string;
74
74
  reason?: string;
75
75
  file_change?: {
76
76
  paths?: string[];
@@ -1,21 +1,35 @@
1
1
  import type { ProviderInvocationProgress } from "../providers/invocation-progress.js";
2
2
  import type { languageDiagnosticFields } from "../communication-language/index.js";
3
+ import type { ChatFailureCode } from "./failures.js";
4
+ import type { WorkflowKind } from "@tutti/shared/domain";
5
+ export type ChatInspectionBlocker = {
6
+ activity_ref: string;
7
+ activity_kind: "run" | "procedure";
8
+ workflow_kind?: WorkflowKind;
9
+ };
3
10
  export type ChatAssistantLogger = {
4
11
  info: (fields: Record<string, unknown>, message: string) => void;
5
12
  warn: (fields: Record<string, unknown>, message: string) => void;
6
13
  };
7
14
  type ChatAssistantProgress = ProviderInvocationProgress | ({
8
15
  stage: "language_context";
9
- } & ReturnType<typeof languageDiagnosticFields>) | {
10
- stage: "queued" | "inspection_wait" | "model_requested" | "reply_persisted" | "failed" | "skipped";
11
- reason_code?: "queue_full" | "stopping" | "context_unavailable" | "answer_failed" | "reply_failed";
16
+ } & ReturnType<typeof languageDiagnosticFields>) | ({
17
+ stage: "inspection_blocked";
18
+ } & ChatInspectionBlocker) | {
19
+ stage: "queued" | "inspection_wait" | "model_requested" | "reply_persisted" | "notification_failed" | "failed" | "skipped";
20
+ reason_code?: "queue_full" | "stopping" | "context_unavailable" | "answer_failed" | "reply_failed" | "request_changed";
21
+ error_code?: ChatFailureCode;
22
+ diagnostic_id?: string;
12
23
  reference_source_count?: number;
24
+ queue_wait_ms?: number;
13
25
  };
14
26
  export declare function createChatAssistantDiagnostics(options: {
15
27
  logger?: ChatAssistantLogger;
16
28
  projectId: string;
17
29
  triggerMessageId: string;
18
30
  scope: string;
31
+ requestRef?: string;
32
+ attemptRef?: string;
19
33
  }): (event: ChatAssistantProgress) => void;
20
34
  export {};
21
35
  //# sourceMappingURL=diagnostics.d.ts.map
@@ -1,18 +1,21 @@
1
1
  import { createEventRef } from "@tutti/shared/ids";
2
2
  export function createChatAssistantDiagnostics(options) {
3
- const requestRef = createEventRef();
3
+ const requestRef = options.requestRef ?? createEventRef();
4
4
  const started = performance.now();
5
5
  return (event) => {
6
6
  try {
7
7
  const fields = {
8
8
  project_id: options.projectId,
9
9
  chat_request_ref: requestRef,
10
+ ...(options.attemptRef === undefined ? {} : { attempt_ref: options.attemptRef }),
10
11
  trigger_message_ref: options.triggerMessageId,
11
12
  scope: options.scope,
12
13
  elapsed_ms: Math.round(performance.now() - started),
13
14
  ...event,
14
15
  };
15
- if (event.stage === "failed" || event.stage === "provider_failed") {
16
+ if (event.stage === "failed" ||
17
+ event.stage === "provider_failed" ||
18
+ event.stage === "notification_failed") {
16
19
  options.logger?.warn(fields, "Chat assistant progress");
17
20
  }
18
21
  else {
@@ -0,0 +1,4 @@
1
+ import type { NoticeLocale } from "../communication-language/notice-locale.js";
2
+ import type { ChatFailureCode } from "./failures.js";
3
+ export declare function chatFailureCopy(code: ChatFailureCode, locale: NoticeLocale): string;
4
+ //# sourceMappingURL=failure-messages.d.ts.map
@@ -0,0 +1,57 @@
1
+ const messages = {
2
+ en: {
3
+ reference_authorization_required: "Authorize document access using the group card, then send your question again. Authorization does not restart this answer.",
4
+ chat_queue_full: "Tutti is busy answering other questions. Try again shortly.",
5
+ chat_context_unavailable: "This question's conversation is no longer available.",
6
+ host_restarted: "The Host restarted before this answer was saved. Send your question again.",
7
+ provider_not_configured: "Ask the project owner to configure model access, then send your question again.",
8
+ provider_auth_invalid: "Model access could not be verified. Ask the project owner to check it.",
9
+ provider_quota_or_billing_required: "Model credit is unavailable. Ask the project owner to check the account.",
10
+ provider_rate_limited: "The model service is busy. Wait a moment, then send your question again.",
11
+ provider_network_error: "The model service could not be reached. Try again when the connection is available.",
12
+ provider_model_unavailable: "The selected model is unavailable. Ask the project owner to check model access.",
13
+ provider_timeout: "The model did not finish answering in time. You can send your question again.",
14
+ provider_output_invalid: "The model did not return a usable answer. You can send your question again.",
15
+ provider_lifecycle_failed: "The model process could not close safely. Restart the Host before trying again.",
16
+ chat_reply_persistence_failed: "The answer could not be saved. Check the Host diagnostics before trying again.",
17
+ internal_error: "Tutti could not complete this read-only answer. Share the diagnostic ID if this persists.",
18
+ },
19
+ "zh-Hans": {
20
+ reference_authorization_required: "请先通过群内卡片授权文档访问,然后重新提问。授权不会自动重启这次回答。",
21
+ chat_queue_full: "Tutti 正在回答其他问题,请稍后再试。",
22
+ chat_context_unavailable: "这条问题所在的对话已不可用。",
23
+ host_restarted: "本机运行时在回答保存前重启了,请重新发送问题。",
24
+ provider_not_configured: "请联系项目负责人配置模型接入,然后重新提问。",
25
+ provider_auth_invalid: "无法验证模型接入,请联系项目负责人检查配置。",
26
+ provider_quota_or_billing_required: "模型额度不可用,请联系项目负责人检查账号。",
27
+ provider_rate_limited: "模型服务繁忙,请稍后重新发送问题。",
28
+ provider_network_error: "无法连接模型服务,请在连接恢复后再试。",
29
+ provider_model_unavailable: "当前模型不可用,请联系项目负责人检查模型接入。",
30
+ provider_timeout: "这次回答超时了,你可以重新发送问题。",
31
+ provider_output_invalid: "模型没有返回可用的回答,你可以重新发送问题。",
32
+ provider_lifecycle_failed: "模型进程未能安全关闭,请重启本机运行时后再试。",
33
+ chat_reply_persistence_failed: "回答未能保存,请先检查本机运行时的诊断信息。",
34
+ internal_error: "Tutti 未能完成这次只读回答。如果问题持续,请提供诊断编号。",
35
+ },
36
+ "zh-Hant": {
37
+ reference_authorization_required: "請先透過群組卡片授權文件存取,然後重新提問。授權不會自動重新啟動這次回答。",
38
+ chat_queue_full: "Tutti 正在回答其他問題,請稍後再試。",
39
+ chat_context_unavailable: "這個問題所在的對話已無法使用。",
40
+ host_restarted: "本機執行環境在回答儲存前重新啟動了,請重新傳送問題。",
41
+ provider_not_configured: "請聯絡專案負責人設定模型連線,然後重新提問。",
42
+ provider_auth_invalid: "無法驗證模型連線,請聯絡專案負責人檢查設定。",
43
+ provider_quota_or_billing_required: "模型額度無法使用,請聯絡專案負責人檢查帳號。",
44
+ provider_rate_limited: "模型服務忙碌,請稍後重新傳送問題。",
45
+ provider_network_error: "無法連線至模型服務,請在連線恢復後再試。",
46
+ provider_model_unavailable: "目前的模型無法使用,請聯絡專案負責人檢查模型連線。",
47
+ provider_timeout: "這次回答逾時了,你可以重新傳送問題。",
48
+ provider_output_invalid: "模型沒有傳回可用的回答,你可以重新傳送問題。",
49
+ provider_lifecycle_failed: "模型程序未能安全關閉,請重新啟動本機執行環境後再試。",
50
+ chat_reply_persistence_failed: "回答未能儲存,請先檢查本機執行環境的診斷資訊。",
51
+ internal_error: "Tutti 未能完成這次唯讀回答。如果問題持續,請提供診斷編號。",
52
+ },
53
+ };
54
+ export function chatFailureCopy(code, locale) {
55
+ return messages[locale][code];
56
+ }
57
+ //# sourceMappingURL=failure-messages.js.map
@@ -0,0 +1,27 @@
1
+ import type { OperationFailure } from "@tutti/shared/schemas/api";
2
+ declare const failures: {
3
+ readonly reference_authorization_required: readonly ["access", "none"];
4
+ readonly chat_queue_full: readonly ["capacity", "resend_request"];
5
+ readonly chat_context_unavailable: readonly ["interrupted", "none"];
6
+ readonly host_restarted: readonly ["interrupted", "resend_request"];
7
+ readonly provider_not_configured: readonly ["configuration", "check_provider"];
8
+ readonly provider_auth_invalid: readonly ["access", "check_provider"];
9
+ readonly provider_quota_or_billing_required: readonly ["access", "check_provider"];
10
+ readonly provider_rate_limited: readonly ["capacity", "resend_request"];
11
+ readonly provider_network_error: readonly ["dependency", "resend_request"];
12
+ readonly provider_model_unavailable: readonly ["configuration", "check_provider"];
13
+ readonly provider_timeout: readonly ["dependency", "resend_request"];
14
+ readonly provider_output_invalid: readonly ["dependency", "resend_request"];
15
+ readonly provider_lifecycle_failed: readonly ["internal", "restart_host"];
16
+ readonly chat_reply_persistence_failed: readonly ["internal", "contact_support"];
17
+ readonly internal_error: readonly ["internal", "contact_support"];
18
+ };
19
+ export type ChatFailureCode = keyof typeof failures;
20
+ type ChatFailure = OperationFailure & {
21
+ code: ChatFailureCode;
22
+ };
23
+ export declare function chatFailure(code: ChatFailureCode, diagnosticId?: string): ChatFailure;
24
+ export declare function chatFailureMessage(failure: OperationFailure, locale?: string): string;
25
+ export declare function classifyChatFailure(error: unknown, diagnosticId: string): ChatFailure;
26
+ export {};
27
+ //# sourceMappingURL=failures.d.ts.map
@@ -0,0 +1,46 @@
1
+ import { createEventRef } from "@tutti/shared/ids";
2
+ import { providerFailureCode } from "../providers/failure-classification.js";
3
+ import { noticeLocale } from "../communication-language/notice-locale.js";
4
+ import { chatFailureCopy } from "./failure-messages.js";
5
+ const failures = {
6
+ reference_authorization_required: ["access", "none"],
7
+ chat_queue_full: ["capacity", "resend_request"],
8
+ chat_context_unavailable: ["interrupted", "none"],
9
+ host_restarted: ["interrupted", "resend_request"],
10
+ provider_not_configured: ["configuration", "check_provider"],
11
+ provider_auth_invalid: ["access", "check_provider"],
12
+ provider_quota_or_billing_required: ["access", "check_provider"],
13
+ provider_rate_limited: ["capacity", "resend_request"],
14
+ provider_network_error: ["dependency", "resend_request"],
15
+ provider_model_unavailable: ["configuration", "check_provider"],
16
+ provider_timeout: ["dependency", "resend_request"],
17
+ provider_output_invalid: ["dependency", "resend_request"],
18
+ provider_lifecycle_failed: ["internal", "restart_host"],
19
+ chat_reply_persistence_failed: ["internal", "contact_support"],
20
+ internal_error: ["internal", "contact_support"],
21
+ };
22
+ export function chatFailure(code, diagnosticId = createEventRef()) {
23
+ const [category, recovery] = failures[code];
24
+ return { code, category, recovery, diagnostic_id: diagnosticId };
25
+ }
26
+ export function chatFailureMessage(failure, locale) {
27
+ const language = noticeLocale(locale);
28
+ const code = Object.hasOwn(failures, failure.code)
29
+ ? failure.code
30
+ : "internal_error";
31
+ const label = language === "zh-Hans" ? "诊断编号" : language === "zh-Hant" ? "診斷編號" : "Diagnostic ID";
32
+ return `${chatFailureCopy(code, language)} ${label}: ${failure.diagnostic_id}`;
33
+ }
34
+ // Allowlisted error facts only; neither error.message nor diagnostic callbacks
35
+ // establish business truth. Unknown failures remain non-automatically-retryable.
36
+ export function classifyChatFailure(error, diagnosticId) {
37
+ const value = typeof error === "object" && error !== null
38
+ ? error
39
+ : {};
40
+ const code = typeof value.code === "string" ? value.code : value.reason;
41
+ const mapped = typeof code === "string" && Object.hasOwn(failures, code)
42
+ ? code
43
+ : (providerFailureCode(error) ?? "internal_error");
44
+ return chatFailure(mapped, diagnosticId);
45
+ }
46
+ //# sourceMappingURL=failures.js.map
@@ -1,6 +1,6 @@
1
- import type { ProjectId } from "@tutti/shared/ids";
1
+ import { type ProjectId } from "@tutti/shared/ids";
2
2
  import type { MessageProjection } from "@tutti/shared/schemas/api";
3
- import { type ChatAssistantLogger } from "./diagnostics.js";
3
+ import { type ChatAssistantLogger, type ChatInspectionBlocker } from "./diagnostics.js";
4
4
  import type { ProviderInvocationProgressObserver } from "../providers/invocation-progress.js";
5
5
  import { type HostProjectStore, type SqliteDatabase } from "../store/index.js";
6
6
  import type { WorkspaceEventBus } from "../server-shell/http/workspace-events.js";
@@ -33,6 +33,7 @@ export type ReadOnlyChatAssistantEnqueueResult = {
33
33
  triggered: boolean;
34
34
  };
35
35
  export type ReadOnlyChatAssistantHandle = {
36
+ register: (tx: SqliteDatabase, message: MessageProjection) => void;
36
37
  enqueue: (input: ReadOnlyChatAssistantTriggerInput) => ReadOnlyChatAssistantEnqueueResult;
37
38
  waitForIdle: () => Promise<void>;
38
39
  stopAccepting: () => void;
@@ -54,7 +55,8 @@ export type ReadOnlyChatAssistantOptions = {
54
55
  triggerMessage: MessageProjection;
55
56
  responseMessage: MessageProjection;
56
57
  }) => void | (() => void);
57
- waitForInspectionAvailability?: () => Promise<void>;
58
+ waitForInspectionAvailability?: (onBlocked: (blocker: ChatInspectionBlocker) => void) => Promise<void>;
59
+ onRequestsChanged?: () => void;
58
60
  maxQueuedMentions?: number;
59
61
  now?: () => Date;
60
62
  };
@@ -62,16 +64,27 @@ export declare function isChatAssistantOutput(value: unknown): value is ChatAssi
62
64
  export declare function containsTuttiMention(value: string): boolean;
63
65
  export declare class ReadOnlyChatAssistant implements ReadOnlyChatAssistantHandle {
64
66
  private readonly options;
65
- private readonly pending;
66
67
  private readonly idleWaiters;
67
68
  private active;
68
69
  private accepting;
69
70
  private readonly maxQueuedMentions;
71
+ private recoveryTimer;
72
+ private started;
73
+ private activeAttemptRef;
74
+ private storageFailureReported;
70
75
  constructor(options: ReadOnlyChatAssistantOptions);
76
+ /** Call once after Host recovery/transport wiring. No old messages are backfilled. */
77
+ start(): void;
78
+ register(tx: SqliteDatabase, message: MessageProjection): void;
79
+ private now;
80
+ private report;
71
81
  enqueue(input: ReadOnlyChatAssistantTriggerInput): ReadOnlyChatAssistantEnqueueResult;
72
82
  waitForIdle(): Promise<void>;
73
83
  stopAccepting(): void;
74
84
  private pump;
85
+ private reportStorageFailure;
86
+ private pumpNext;
87
+ private notifyRequestsChanged;
75
88
  private resolveIdleIfNeeded;
76
89
  private buildMainChatContext;
77
90
  private buildClarificationRoundContext;
@@ -80,6 +93,7 @@ export declare class ReadOnlyChatAssistant implements ReadOnlyChatAssistantHandl
80
93
  private appendMainChatAssistantMessage;
81
94
  private appendClarificationRoundAssistantMessage;
82
95
  private appendAssistantMessageForTrigger;
96
+ private recordReply;
83
97
  private respond;
84
98
  }
85
99
  //# sourceMappingURL=index.d.ts.map