@xfey/tutti 0.1.102 → 0.1.104
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 +9 -4
- package/dist/chat-assistant/index.d.ts +6 -1
- package/dist/chat-assistant/index.js +22 -12
- package/dist/collaboration-ingestion/external-source.d.ts +15 -0
- package/dist/collaboration-ingestion/external-source.js +120 -0
- package/dist/collaboration-ingestion/index.d.ts +5 -0
- package/dist/collaboration-ingestion/index.js +4 -0
- package/dist/collaboration-ingestion/invalidations.d.ts +4 -0
- package/dist/collaboration-ingestion/invalidations.js +15 -0
- package/dist/collaboration-ingestion/main-chat.d.ts +33 -0
- package/dist/collaboration-ingestion/main-chat.js +67 -0
- package/dist/collaboration-ingestion/reference-files.d.ts +29 -0
- package/dist/collaboration-ingestion/reference-files.js +158 -0
- package/dist/collaboration-ingestion/types.d.ts +19 -0
- package/dist/collaboration-ingestion/types.js +2 -0
- package/dist/platform-outbound/coordinator.d.ts +17 -0
- package/dist/platform-outbound/coordinator.js +48 -0
- package/dist/platform-outbound/index.d.ts +5 -0
- package/dist/platform-outbound/index.js +5 -0
- package/dist/platform-outbound/repository.d.ts +30 -0
- package/dist/platform-outbound/repository.js +108 -0
- package/dist/platform-outbound/types.d.ts +38 -0
- package/dist/platform-outbound/types.js +2 -0
- package/dist/platform-outbound/worker.d.ts +36 -0
- package/dist/platform-outbound/worker.js +164 -0
- package/dist/server-shell/cli/cli.js +9 -0
- package/dist/server-shell/cli/errors.d.ts +1 -1
- package/dist/server-shell/cli/host-lifecycle.d.ts +2 -0
- package/dist/server-shell/cli/host-lifecycle.js +34 -1
- package/dist/server-shell/cli/host-relay-connection-manager.js +22 -11
- package/dist/server-shell/cli/host-relay-status.js +1 -0
- package/dist/server-shell/cli/host-runtime-endpoint.js +17 -1
- package/dist/server-shell/cli/host-server-runtime.d.ts +2 -0
- package/dist/server-shell/cli/host-server-runtime.js +88 -14
- package/dist/server-shell/cli/launch-command.d.ts +7 -0
- package/dist/server-shell/cli/launch-command.js +39 -1
- package/dist/server-shell/cli/launch.d.ts +2 -0
- package/dist/server-shell/cli/launch.js +3 -0
- package/dist/server-shell/cli/machine-local.d.ts +20 -0
- package/dist/server-shell/cli/machine-local.js +61 -1
- package/dist/server-shell/cli/managed-host.d.ts +16 -1
- package/dist/server-shell/cli/managed-host.js +191 -23
- package/dist/server-shell/cli/relay-registration.d.ts +4 -1
- package/dist/server-shell/cli/relay-registration.js +36 -7
- package/dist/server-shell/cli/runtime-commands.d.ts +5 -1
- package/dist/server-shell/cli/runtime-commands.js +9 -3
- package/dist/server-shell/http/host-tunnel.d.ts +5 -0
- package/dist/server-shell/http/host-tunnel.js +109 -0
- package/dist/server-shell/http/routes/local-control.d.ts +2 -0
- package/dist/server-shell/http/routes/local-control.js +2 -0
- package/dist/server-shell/http/routes/project-api/invalidations.d.ts +0 -1
- package/dist/server-shell/http/routes/project-api/invalidations.js +0 -3
- package/dist/server-shell/http/routes/project-api/messages-routes.js +32 -63
- package/dist/server-shell/http/routes/project-api/openapi-workspace-routes.d.ts +8 -4
- package/dist/server-shell/http/routes/project-api/openapi.d.ts +8 -4
- package/dist/server-shell/http/routes/project-api/reference-files-routes.js +25 -94
- package/dist/server-shell/http/routes/project-api/reference-files.d.ts +1 -11
- package/dist/server-shell/http/routes/project-api/reference-files.js +2 -87
- package/dist/server-shell/http/routes/project-api/schemas.d.ts +8 -4
- package/dist/server-shell/http/routes/project-api/schemas.js +8 -3
- package/dist/server-shell/http/routes/project-api/session-requirements.js +34 -2
- package/dist/server-shell/http/routes/project-api/types.d.ts +3 -1
- package/dist/server-shell/http/routes/project-api/workspace-projections.js +8 -2
- package/dist/server-shell/local-console/package-update-hosts.js +4 -1
- package/dist/server-shell/local-console/project-service.d.ts +11 -2
- package/dist/server-shell/local-console/project-service.js +36 -8
- package/dist/server-shell/local-console/server.js +6 -1
- package/dist/server-shell/local-console/session.d.ts +4 -0
- package/dist/server-shell/local-console/session.js +14 -0
- package/dist/server-shell/session/relay-session-context.d.ts +12 -1
- package/dist/server-shell/session/relay-session-context.js +19 -1
- package/migrations/0016_external_source_mappings.sql +141 -0
- package/migrations/0017_platform_outbound_intents.sql +31 -0
- package/migrations/README.md +3 -1
- package/node_modules/@tutti/relay-client/dist/host-control.d.ts +26 -1
- package/node_modules/@tutti/relay-client/dist/host-control.js +62 -0
- package/node_modules/@tutti/relay-client/dist/tunnel-frames.js +32 -6
- package/node_modules/@tutti/relay-client/dist/tunnel-types.d.ts +5 -1
- package/node_modules/@tutti/shared/dist/domain/index.d.ts +9 -0
- package/node_modules/@tutti/shared/dist/domain/index.js +14 -0
- package/node_modules/@tutti/shared/dist/ids/index.d.ts +6 -0
- package/node_modules/@tutti/shared/dist/ids/index.js +4 -0
- package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +4 -0
- package/node_modules/@tutti/shared/dist/schemas/api/index.js +2 -0
- package/node_modules/@tutti/shared/dist/schemas/api/local-console-account-handoffs.d.ts +13 -0
- package/node_modules/@tutti/shared/dist/schemas/api/local-console-account-handoffs.js +16 -0
- package/node_modules/@tutti/shared/dist/schemas/api/platform-sessions.d.ts +43 -0
- package/node_modules/@tutti/shared/dist/schemas/api/platform-sessions.js +44 -0
- package/node_modules/@tutti/shared/dist/schemas/domain/index.d.ts +7 -0
- package/node_modules/@tutti/shared/dist/schemas/domain/index.js +10 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/index.d.ts +29 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/index.js +24 -1
- package/node_modules/@tutti/shared/dist/schemas/internal/platform-integration.d.ts +1346 -0
- package/node_modules/@tutti/shared/dist/schemas/internal/platform-integration.js +516 -0
- package/node_modules/@tutti/shared/dist/utils/feishu-diagnostics/index.d.ts +10 -0
- package/node_modules/@tutti/shared/dist/utils/feishu-diagnostics/index.js +19 -0
- package/node_modules/@tutti/shared/dist/utils/index.d.ts +1 -0
- package/node_modules/@tutti/shared/dist/utils/index.js +1 -0
- package/node_modules/@tutti/shared/dist/utils/redaction/index.d.ts +1 -1
- package/node_modules/@tutti/shared/dist/utils/redaction/index.js +18 -0
- package/package.json +1 -1
- package/web/assets/{homepage-motion-scene-BtT5bd30.js → homepage-motion-scene-DEVrQ9aj.js} +1 -1
- package/web/assets/{index-CxCTqGFO.css → index-6i9Uk7fS.css} +1 -1
- package/web/assets/index-Lxtst2sl.js +69 -0
- package/web/index.html +2 -2
- package/web/assets/index-DtiStc-n.js +0 -69
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { GetMessagesRequestSchema, MessageWindowSchema, SendMainChatMessageBodySchema, SendMainChatMessageResponseSchema, } from "@tutti/shared/schemas/api";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { createArtifactFeedbackMessage } from "../../../../artifact-feedback/index.js";
|
|
3
|
+
import { ingestMainChatMessage } from "../../../../collaboration-ingestion/index.js";
|
|
4
|
+
import { readMainChatMessageWindow } from "../../../../collaboration-state/index.js";
|
|
5
5
|
import { HOST_PROJECT_API_BASE_PATH } from "./constants.js";
|
|
6
|
-
import { mainChatMessageInvalidates } from "./invalidations.js";
|
|
7
6
|
import { requireValidMessageWindowRequest, requireValidSendMainChatPayload, } from "./payload-validation.js";
|
|
8
7
|
import { requireHostProjectSession, requireProjectStore, requireWorkspaceRoot, } from "./session-requirements.js";
|
|
9
8
|
export function registerMessagesRoutes(app, { options, workspaceEvents, artifactPreviewManager, }) {
|
|
@@ -30,83 +29,53 @@ export function registerMessagesRoutes(app, { options, workspaceEvents, artifact
|
|
|
30
29
|
const session = requireHostProjectSession(request, options);
|
|
31
30
|
const store = requireProjectStore(options);
|
|
32
31
|
const payload = requireValidSendMainChatPayload(request.body.payload);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
return ingestMainChatMessage({
|
|
33
|
+
store,
|
|
34
|
+
events: workspaceEvents,
|
|
35
|
+
commandId: request.body.command_id,
|
|
36
|
+
payload,
|
|
37
|
+
author: session.account,
|
|
39
38
|
...(options.now === undefined ? {} : { now: options.now }),
|
|
40
|
-
|
|
41
|
-
let body;
|
|
42
|
-
let refs;
|
|
39
|
+
materialize: () => {
|
|
43
40
|
if ("artifact_feedback" in payload) {
|
|
44
41
|
const projection = artifactPreviewManager.readProjection({
|
|
45
42
|
workspaceRoot: requireWorkspaceRoot(options),
|
|
46
43
|
});
|
|
47
44
|
if (projection.artifact.status !== "declared" ||
|
|
48
45
|
projection.artifact.preview.status !== "ready") {
|
|
49
|
-
return {
|
|
46
|
+
return {
|
|
47
|
+
kind: "rejected",
|
|
48
|
+
disposition: { kind: "artifact_unavailable" },
|
|
49
|
+
};
|
|
50
50
|
}
|
|
51
51
|
if (projection.artifact.preview_generation !==
|
|
52
52
|
payload.artifact_feedback.expected_preview_generation) {
|
|
53
|
-
return {
|
|
53
|
+
return {
|
|
54
|
+
kind: "rejected",
|
|
55
|
+
disposition: { kind: "artifact_changed" },
|
|
56
|
+
};
|
|
54
57
|
}
|
|
55
58
|
const feedbackMessage = createArtifactFeedbackMessage({
|
|
56
59
|
artifactTitle: projection.artifact.artifact.title,
|
|
57
60
|
feedback: payload.artifact_feedback,
|
|
58
61
|
});
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
return {
|
|
63
|
+
kind: "message",
|
|
64
|
+
body: feedbackMessage.body,
|
|
65
|
+
refs: { artifact_feedback: feedbackMessage.ref },
|
|
66
|
+
};
|
|
61
67
|
}
|
|
62
|
-
|
|
63
|
-
body = payload.body;
|
|
64
|
-
}
|
|
65
|
-
const message = createMainChatMessage(tx, {
|
|
66
|
-
body,
|
|
67
|
-
author: {
|
|
68
|
-
kind: "human",
|
|
69
|
-
ref: session.account.account_ref,
|
|
70
|
-
display_name: session.account.display_name,
|
|
71
|
-
avatar: session.account.avatar,
|
|
72
|
-
},
|
|
73
|
-
...(refs === undefined ? {} : { refs }),
|
|
74
|
-
...(options.now === undefined ? {} : { now: options.now }),
|
|
75
|
-
});
|
|
76
|
-
return {
|
|
77
|
-
disposition: { kind: "created", message_id: message.id },
|
|
78
|
-
result: { message },
|
|
79
|
-
};
|
|
68
|
+
return { kind: "message", body: payload.body };
|
|
80
69
|
},
|
|
70
|
+
...(options.controlPlane === undefined
|
|
71
|
+
? {}
|
|
72
|
+
: {
|
|
73
|
+
scratchpadSource: {
|
|
74
|
+
notify: (message) => options.controlPlane?.notifyScratchpadSourceChanged(message),
|
|
75
|
+
},
|
|
76
|
+
}),
|
|
77
|
+
...(options.chatAssistant === undefined ? {} : { chatAssistant: options.chatAssistant }),
|
|
81
78
|
});
|
|
82
|
-
const replayedMessage = execution.result === undefined &&
|
|
83
|
-
execution.disposition.kind === "created" &&
|
|
84
|
-
execution.disposition.message_id !== undefined
|
|
85
|
-
? readMessageProjectionById(store.db, execution.disposition.message_id)
|
|
86
|
-
: null;
|
|
87
|
-
const result = execution.result ?? (replayedMessage === null ? undefined : { message: replayedMessage });
|
|
88
|
-
const response = {
|
|
89
|
-
command_id: execution.command_id,
|
|
90
|
-
disposition: execution.disposition,
|
|
91
|
-
...(execution.disposition.kind === "created"
|
|
92
|
-
? { invalidates: mainChatMessageInvalidates() }
|
|
93
|
-
: {}),
|
|
94
|
-
};
|
|
95
|
-
if (result !== undefined) {
|
|
96
|
-
response.result = result;
|
|
97
|
-
}
|
|
98
|
-
if (!execution.replayed && result !== undefined) {
|
|
99
|
-
workspaceEvents.publish({
|
|
100
|
-
event_type: "message.created",
|
|
101
|
-
payload: {
|
|
102
|
-
message: result.message,
|
|
103
|
-
},
|
|
104
|
-
invalidates: mainChatMessageInvalidates(),
|
|
105
|
-
});
|
|
106
|
-
options.controlPlane?.notifyScratchpadSourceChanged(result.message);
|
|
107
|
-
options.chatAssistant?.enqueue({ message: result.message });
|
|
108
|
-
}
|
|
109
|
-
return response;
|
|
110
79
|
});
|
|
111
80
|
}
|
|
112
81
|
//# sourceMappingURL=messages-routes.js.map
|
|
@@ -429,10 +429,12 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
|
|
|
429
429
|
readonly required: readonly ["client_session_id", "transport", "connected_at"];
|
|
430
430
|
readonly additionalProperties: false;
|
|
431
431
|
readonly properties: {
|
|
432
|
-
readonly client_session_id:
|
|
432
|
+
readonly client_session_id: {
|
|
433
|
+
readonly oneOf: readonly [import("@sinclair/typebox").TString, import("@sinclair/typebox").TString];
|
|
434
|
+
};
|
|
433
435
|
readonly transport: {
|
|
434
436
|
readonly type: "string";
|
|
435
|
-
readonly enum: readonly ["relay_tunnel"];
|
|
437
|
+
readonly enum: readonly ["relay_tunnel", "feishu_platform_session"];
|
|
436
438
|
};
|
|
437
439
|
readonly connected_at: import("@sinclair/typebox").TString;
|
|
438
440
|
};
|
|
@@ -895,10 +897,12 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
|
|
|
895
897
|
readonly required: readonly ["client_session_id", "transport", "connected_at"];
|
|
896
898
|
readonly additionalProperties: false;
|
|
897
899
|
readonly properties: {
|
|
898
|
-
readonly client_session_id:
|
|
900
|
+
readonly client_session_id: {
|
|
901
|
+
readonly oneOf: readonly [import("@sinclair/typebox").TString, import("@sinclair/typebox").TString];
|
|
902
|
+
};
|
|
899
903
|
readonly transport: {
|
|
900
904
|
readonly type: "string";
|
|
901
|
-
readonly enum: readonly ["relay_tunnel"];
|
|
905
|
+
readonly enum: readonly ["relay_tunnel", "feishu_platform_session"];
|
|
902
906
|
};
|
|
903
907
|
readonly connected_at: import("@sinclair/typebox").TString;
|
|
904
908
|
};
|
|
@@ -1712,10 +1712,12 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
|
|
|
1712
1712
|
readonly required: readonly ["client_session_id", "transport", "connected_at"];
|
|
1713
1713
|
readonly additionalProperties: false;
|
|
1714
1714
|
readonly properties: {
|
|
1715
|
-
readonly client_session_id:
|
|
1715
|
+
readonly client_session_id: {
|
|
1716
|
+
readonly oneOf: readonly [import("@sinclair/typebox").TString, import("@sinclair/typebox").TString];
|
|
1717
|
+
};
|
|
1716
1718
|
readonly transport: {
|
|
1717
1719
|
readonly type: "string";
|
|
1718
|
-
readonly enum: readonly ["relay_tunnel"];
|
|
1720
|
+
readonly enum: readonly ["relay_tunnel", "feishu_platform_session"];
|
|
1719
1721
|
};
|
|
1720
1722
|
readonly connected_at: import("@sinclair/typebox").TString;
|
|
1721
1723
|
};
|
|
@@ -2178,10 +2180,12 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
|
|
|
2178
2180
|
readonly required: readonly ["client_session_id", "transport", "connected_at"];
|
|
2179
2181
|
readonly additionalProperties: false;
|
|
2180
2182
|
readonly properties: {
|
|
2181
|
-
readonly client_session_id:
|
|
2183
|
+
readonly client_session_id: {
|
|
2184
|
+
readonly oneOf: readonly [import("@sinclair/typebox").TString, import("@sinclair/typebox").TString];
|
|
2185
|
+
};
|
|
2182
2186
|
readonly transport: {
|
|
2183
2187
|
readonly type: "string";
|
|
2184
|
-
readonly enum: readonly ["relay_tunnel"];
|
|
2188
|
+
readonly enum: readonly ["relay_tunnel", "feishu_platform_session"];
|
|
2185
2189
|
};
|
|
2186
2190
|
readonly connected_at: import("@sinclair/typebox").TString;
|
|
2187
2191
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { GetReferenceFilesRequestSchema, GetReferenceFilesResponseSchema, RefreshReferenceSummariesBodySchema, RefreshReferenceSummariesResponseSchema, UploadReferenceFileBodySchema, UploadReferenceFileResponseSchema, } from "@tutti/shared/schemas/api";
|
|
2
|
-
import {
|
|
3
|
-
import { REFERENCE_DIRECTORY_PATH
|
|
2
|
+
import { ingestReferenceFile, REFERENCE_FILE_INGESTION_COMMAND_NAME, REFERENCE_FILE_INGESTION_TARGET_REF, } from "../../../../collaboration-ingestion/index.js";
|
|
3
|
+
import { REFERENCE_DIRECTORY_PATH } from "../../../../workspace-ops/index.js";
|
|
4
4
|
import { decideCommandIdempotencyReplay, executeIdempotentCommand, readCommandIdempotencyRecord, } from "../../../command-idempotency/index.js";
|
|
5
5
|
import { HOST_PROJECT_API_BASE_PATH } from "./constants.js";
|
|
6
|
-
import { readReferenceFilesResponse,
|
|
6
|
+
import { readReferenceFilesResponse, referenceSummaryProcedureInvalidates, } from "./reference-files.js";
|
|
7
7
|
import { requireControlPlane, requireHostProjectSession, requireProjectStore, requireWorkspaceRoot, } from "./session-requirements.js";
|
|
8
8
|
import { abortDownloadedStagedUpload, cleanupDownloadedStagedUpload, downloadStagedUpload, } from "./staged-uploads.js";
|
|
9
9
|
export function registerReferenceFilesRoutes(app, { options, workspaceEvents, }) {
|
|
@@ -33,8 +33,8 @@ export function registerReferenceFilesRoutes(app, { options, workspaceEvents, })
|
|
|
33
33
|
const store = requireProjectStore(options);
|
|
34
34
|
const commandId = request.body.command_id;
|
|
35
35
|
const command = {
|
|
36
|
-
command_name:
|
|
37
|
-
target_ref:
|
|
36
|
+
command_name: REFERENCE_FILE_INGESTION_COMMAND_NAME,
|
|
37
|
+
target_ref: REFERENCE_FILE_INGESTION_TARGET_REF,
|
|
38
38
|
payload: request.body.payload,
|
|
39
39
|
};
|
|
40
40
|
const replay = decideCommandIdempotencyReplay(readCommandIdempotencyRecord(store.db, commandId), command);
|
|
@@ -48,101 +48,32 @@ export function registerReferenceFilesRoutes(app, { options, workspaceEvents, })
|
|
|
48
48
|
purpose: "reference_file",
|
|
49
49
|
})
|
|
50
50
|
: undefined;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
target_ref: command.target_ref,
|
|
51
|
+
return await ingestReferenceFile({
|
|
52
|
+
store,
|
|
53
|
+
workspaceRoot: requireWorkspaceRoot(options),
|
|
54
|
+
events: workspaceEvents,
|
|
55
|
+
commandId,
|
|
57
56
|
payload: request.body.payload,
|
|
57
|
+
content: staged?.content,
|
|
58
|
+
author: session.account,
|
|
58
59
|
...(options.now === undefined ? {} : { now: options.now }),
|
|
59
|
-
|
|
60
|
-
if (staged
|
|
61
|
-
|
|
60
|
+
afterCommit: async () => {
|
|
61
|
+
if (staged !== undefined) {
|
|
62
|
+
await cleanupDownloadedStagedUpload(staged);
|
|
63
|
+
staged = undefined;
|
|
62
64
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
? {}
|
|
70
|
-
: { mediaType: request.body.payload.media_type }),
|
|
71
|
-
...(request.body.payload.note === undefined
|
|
72
|
-
? {}
|
|
73
|
-
: { note: request.body.payload.note }),
|
|
74
|
-
...(options.now === undefined ? {} : { now: options.now }),
|
|
75
|
-
});
|
|
76
|
-
const file = toReferenceFileProjection({
|
|
77
|
-
workspaceRoot: requireWorkspaceRoot(options),
|
|
78
|
-
entry: uploaded.file,
|
|
79
|
-
...(options.now === undefined ? {} : { now: options.now }),
|
|
80
|
-
});
|
|
81
|
-
const message = createMainChatMessage(tx, {
|
|
82
|
-
body: referenceUploadMessageBody(file),
|
|
83
|
-
author: {
|
|
84
|
-
kind: "human",
|
|
85
|
-
ref: session.account.account_ref,
|
|
86
|
-
display_name: session.account.display_name,
|
|
87
|
-
avatar: session.account.avatar,
|
|
88
|
-
},
|
|
89
|
-
refs: {
|
|
90
|
-
reference_file: referenceFileMessageRef(file),
|
|
91
|
-
},
|
|
92
|
-
...(options.now === undefined ? {} : { now: options.now }),
|
|
93
|
-
});
|
|
94
|
-
recordReadNotificationEvent(tx, {
|
|
95
|
-
scope: "references",
|
|
96
|
-
source_kind: "reference_file",
|
|
97
|
-
source_ref: file.path,
|
|
98
|
-
actor: {
|
|
99
|
-
kind: "human",
|
|
100
|
-
ref: session.account.account_ref,
|
|
65
|
+
},
|
|
66
|
+
...(options.controlPlane === undefined
|
|
67
|
+
? {}
|
|
68
|
+
: {
|
|
69
|
+
scratchpadSource: {
|
|
70
|
+
notify: (message) => options.controlPlane?.notifyScratchpadSourceChanged(message),
|
|
101
71
|
},
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
disposition: { kind: "created" },
|
|
106
|
-
result: {
|
|
107
|
-
file,
|
|
108
|
-
message,
|
|
109
|
-
index_path: uploaded.index_path,
|
|
72
|
+
referenceSummaries: {
|
|
73
|
+
start: (paths) => options.controlPlane?.startReferenceSummaryRefresh({ paths }),
|
|
110
74
|
},
|
|
111
|
-
}
|
|
112
|
-
},
|
|
75
|
+
}),
|
|
113
76
|
});
|
|
114
|
-
const response = {
|
|
115
|
-
command_id: execution.command_id,
|
|
116
|
-
disposition: execution.disposition,
|
|
117
|
-
invalidates,
|
|
118
|
-
};
|
|
119
|
-
if (execution.result !== undefined) {
|
|
120
|
-
response.result = execution.result;
|
|
121
|
-
}
|
|
122
|
-
if (!execution.replayed && execution.result !== undefined) {
|
|
123
|
-
if (staged !== undefined) {
|
|
124
|
-
await cleanupDownloadedStagedUpload(staged);
|
|
125
|
-
staged = undefined;
|
|
126
|
-
}
|
|
127
|
-
workspaceEvents.publish({
|
|
128
|
-
event_type: "message.created",
|
|
129
|
-
payload: { message: execution.result.message },
|
|
130
|
-
invalidates,
|
|
131
|
-
});
|
|
132
|
-
workspaceEvents.publish({
|
|
133
|
-
event_type: "query.invalidate",
|
|
134
|
-
payload: {
|
|
135
|
-
reason: "viewer_changed",
|
|
136
|
-
message: "Reference files changed.",
|
|
137
|
-
},
|
|
138
|
-
invalidates,
|
|
139
|
-
});
|
|
140
|
-
options.controlPlane?.notifyScratchpadSourceChanged(execution.result.message);
|
|
141
|
-
options.controlPlane?.startReferenceSummaryRefresh({
|
|
142
|
-
paths: [execution.result.file.path],
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
return response;
|
|
146
77
|
}
|
|
147
78
|
catch (error) {
|
|
148
79
|
if (staged !== undefined) {
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
import type { GetReferenceFilesRequest, GetReferenceFilesResponse,
|
|
2
|
-
import { readReferenceSummaryIndex, type ViewerTreeEntry } from "../../../../workspace-ops/index.js";
|
|
3
|
-
export declare function toReferenceFileProjection(options: {
|
|
4
|
-
workspaceRoot: string;
|
|
5
|
-
entry: ViewerTreeEntry;
|
|
6
|
-
summaryIndex?: ReturnType<typeof readReferenceSummaryIndex>;
|
|
7
|
-
now?: () => Date;
|
|
8
|
-
}): ReferenceFileProjection;
|
|
1
|
+
import type { GetReferenceFilesRequest, GetReferenceFilesResponse, QueryInvalidationHint } from "@tutti/shared/schemas/api";
|
|
9
2
|
export declare function readReferenceFilesResponse(options: {
|
|
10
3
|
workspaceRoot: string;
|
|
11
4
|
now?: () => Date;
|
|
12
5
|
}, query: GetReferenceFilesRequest): GetReferenceFilesResponse;
|
|
13
|
-
export declare function referenceFilesChangedInvalidates(): QueryInvalidationHint[];
|
|
14
6
|
export declare function referenceSummaryProcedureInvalidates(): QueryInvalidationHint[];
|
|
15
|
-
export declare function referenceUploadMessageBody(file: ReferenceFileProjection): string;
|
|
16
|
-
export declare function referenceFileMessageRef(file: ReferenceFileProjection): NonNullable<NonNullable<MessageCreatedEventPayload["message"]["refs"]>["reference_file"]>;
|
|
17
7
|
//# sourceMappingURL=reference-files.d.ts.map
|
|
@@ -1,61 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { toReferenceFileProjection } from "../../../../collaboration-ingestion/index.js";
|
|
2
|
+
import { REFERENCE_DIRECTORY_PATH, REFERENCE_FILES_DIRECTORY_PATH, REFERENCE_IMAGES_DIRECTORY_PATH, REFERENCE_INDEX_PATH, WorkspaceOpsError, readReferenceFileEntries, readReferenceSummaryIndex, readViewerFile, readViewerSnapshot, referenceFileCategoryForPath, } from "../../../../workspace-ops/index.js";
|
|
2
3
|
import { paginateViewerItems, viewerPageLimit } from "./viewer-projections.js";
|
|
3
|
-
function unreadableReasonForReferenceContent(content) {
|
|
4
|
-
if (content.kind === "text") {
|
|
5
|
-
return undefined;
|
|
6
|
-
}
|
|
7
|
-
return content.reason;
|
|
8
|
-
}
|
|
9
|
-
function referenceTextReadProjection(workspaceRoot, entry, now) {
|
|
10
|
-
if (entry.size_bytes !== undefined && entry.size_bytes > VIEWER_HARD_READ_LIMIT_BYTES) {
|
|
11
|
-
return { can_read: false, blocked_reason: "too_large" };
|
|
12
|
-
}
|
|
13
|
-
try {
|
|
14
|
-
const file = readViewerFile({
|
|
15
|
-
workspaceRoot,
|
|
16
|
-
path: entry.path,
|
|
17
|
-
maxBytes: 1,
|
|
18
|
-
...(now === undefined ? {} : { now }),
|
|
19
|
-
});
|
|
20
|
-
const reason = unreadableReasonForReferenceContent(file.content);
|
|
21
|
-
if (reason !== undefined) {
|
|
22
|
-
return { can_read: false, blocked_reason: reason };
|
|
23
|
-
}
|
|
24
|
-
return { can_read: true };
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return { can_read: false, blocked_reason: "unknown" };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
export function toReferenceFileProjection(options) {
|
|
31
|
-
const category = referenceFileCategoryForPath(options.entry.path) ?? "file";
|
|
32
|
-
const summaryIndex = options.summaryIndex ?? readReferenceSummaryIndex({ workspaceRoot: options.workspaceRoot });
|
|
33
|
-
const projection = {
|
|
34
|
-
path: options.entry.path,
|
|
35
|
-
name: options.entry.name,
|
|
36
|
-
category,
|
|
37
|
-
size_bytes: options.entry.size_bytes ?? 0,
|
|
38
|
-
text_read: referenceTextReadProjection(options.workspaceRoot, options.entry, options.now),
|
|
39
|
-
summary: referenceSummaryProjectionForEntry({
|
|
40
|
-
entry: options.entry,
|
|
41
|
-
summaries: summaryIndex,
|
|
42
|
-
}),
|
|
43
|
-
};
|
|
44
|
-
if (options.entry.blob_oid !== undefined) {
|
|
45
|
-
projection.blob_oid = options.entry.blob_oid;
|
|
46
|
-
}
|
|
47
|
-
if (options.entry.extension !== undefined) {
|
|
48
|
-
projection.extension = options.entry.extension;
|
|
49
|
-
}
|
|
50
|
-
if (options.entry.language_hint !== undefined) {
|
|
51
|
-
projection.language_hint = options.entry.language_hint;
|
|
52
|
-
}
|
|
53
|
-
const mediaType = referenceMediaTypeForPath(options.entry.path);
|
|
54
|
-
if (mediaType !== undefined) {
|
|
55
|
-
projection.media_type = mediaType;
|
|
56
|
-
}
|
|
57
|
-
return projection;
|
|
58
|
-
}
|
|
59
4
|
function referenceDirectoryProjection(options) {
|
|
60
5
|
if (options.directoryStatus === "missing") {
|
|
61
6
|
return {
|
|
@@ -171,37 +116,7 @@ export function readReferenceFilesResponse(options, query) {
|
|
|
171
116
|
page: page.page,
|
|
172
117
|
};
|
|
173
118
|
}
|
|
174
|
-
export function referenceFilesChangedInvalidates() {
|
|
175
|
-
return [
|
|
176
|
-
{ kind: "viewer", path: REFERENCE_DIRECTORY_PATH },
|
|
177
|
-
{ kind: "messages", scope: "main_chat" },
|
|
178
|
-
{ kind: "execution_status" },
|
|
179
|
-
{ kind: "workspace" },
|
|
180
|
-
{ kind: "read_state" },
|
|
181
|
-
{ kind: "bootstrap" },
|
|
182
|
-
];
|
|
183
|
-
}
|
|
184
119
|
export function referenceSummaryProcedureInvalidates() {
|
|
185
120
|
return [{ kind: "execution_status" }, { kind: "bootstrap" }];
|
|
186
121
|
}
|
|
187
|
-
export function referenceUploadMessageBody(file) {
|
|
188
|
-
return file.category === "image" ? `Uploaded image: ${file.name}` : `Uploaded file: ${file.name}`;
|
|
189
|
-
}
|
|
190
|
-
export function referenceFileMessageRef(file) {
|
|
191
|
-
const ref = {
|
|
192
|
-
path: file.path,
|
|
193
|
-
name: file.name,
|
|
194
|
-
source: "human_upload",
|
|
195
|
-
category: file.category,
|
|
196
|
-
size_bytes: file.size_bytes,
|
|
197
|
-
text_read: file.text_read,
|
|
198
|
-
};
|
|
199
|
-
if (file.media_type !== undefined) {
|
|
200
|
-
ref.media_type = file.media_type;
|
|
201
|
-
}
|
|
202
|
-
if (file.blob_oid !== undefined) {
|
|
203
|
-
ref.blob_oid = file.blob_oid;
|
|
204
|
-
}
|
|
205
|
-
return ref;
|
|
206
|
-
}
|
|
207
122
|
//# sourceMappingURL=reference-files.js.map
|
|
@@ -415,10 +415,12 @@ export declare const SessionResponseSchema: {
|
|
|
415
415
|
readonly required: readonly ["client_session_id", "transport", "connected_at"];
|
|
416
416
|
readonly additionalProperties: false;
|
|
417
417
|
readonly properties: {
|
|
418
|
-
readonly client_session_id:
|
|
418
|
+
readonly client_session_id: {
|
|
419
|
+
readonly oneOf: readonly [import("@sinclair/typebox").TString, import("@sinclair/typebox").TString];
|
|
420
|
+
};
|
|
419
421
|
readonly transport: {
|
|
420
422
|
readonly type: "string";
|
|
421
|
-
readonly enum: readonly ["relay_tunnel"];
|
|
423
|
+
readonly enum: readonly ["relay_tunnel", "feishu_platform_session"];
|
|
422
424
|
};
|
|
423
425
|
readonly connected_at: import("@sinclair/typebox").TString;
|
|
424
426
|
};
|
|
@@ -859,10 +861,12 @@ export declare const BootstrapResponseSchema: {
|
|
|
859
861
|
readonly required: readonly ["client_session_id", "transport", "connected_at"];
|
|
860
862
|
readonly additionalProperties: false;
|
|
861
863
|
readonly properties: {
|
|
862
|
-
readonly client_session_id:
|
|
864
|
+
readonly client_session_id: {
|
|
865
|
+
readonly oneOf: readonly [import("@sinclair/typebox").TString, import("@sinclair/typebox").TString];
|
|
866
|
+
};
|
|
863
867
|
readonly transport: {
|
|
864
868
|
readonly type: "string";
|
|
865
|
-
readonly enum: readonly ["relay_tunnel"];
|
|
869
|
+
readonly enum: readonly ["relay_tunnel", "feishu_platform_session"];
|
|
866
870
|
};
|
|
867
871
|
readonly connected_at: import("@sinclair/typebox").TString;
|
|
868
872
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApprovalRequestIdSchema, ClarificationRoundRefSchema, ClarificationThreadRefSchema, IdempotencyKeySchema, IsoDateTimeStringSchema, ProjectIdSchema, RelayAccountRefSchema, RelayClientSessionIdSchema, RelayProjectRefSchema, RecoverySummaryIdSchema, TaskIdSchema, } from "@tutti/shared/schemas/domain";
|
|
1
|
+
import { ApprovalRequestIdSchema, ClarificationRoundRefSchema, ClarificationThreadRefSchema, IdempotencyKeySchema, IsoDateTimeStringSchema, ProjectIdSchema, RelayAccountRefSchema, RelayClientSessionIdSchema, RelayPlatformSessionRefSchema, RelayProjectRefSchema, RecoverySummaryIdSchema, TaskIdSchema, } from "@tutti/shared/schemas/domain";
|
|
2
2
|
import { ActiveClarificationProjectionSchema, ActiveApprovalProjectionSchema, ExecutionStatusProjectionSchema, MessageWindowSchema, ProjectTimelineResponseSchema, ReadStateSummaryProjectionSchema, ScratchpadProjectionSchema, WorklistProjectionSchema, } from "@tutti/shared/schemas/api";
|
|
3
3
|
import { ACCOUNT_AVATAR_COLORS } from "@tutti/shared/domain";
|
|
4
4
|
import { HOST_MAINLINE_BRANCH } from "./constants.js";
|
|
@@ -212,8 +212,13 @@ export const SessionResponseSchema = {
|
|
|
212
212
|
required: ["client_session_id", "transport", "connected_at"],
|
|
213
213
|
additionalProperties: false,
|
|
214
214
|
properties: {
|
|
215
|
-
client_session_id:
|
|
216
|
-
|
|
215
|
+
client_session_id: {
|
|
216
|
+
oneOf: [RelayClientSessionIdSchema, RelayPlatformSessionRefSchema],
|
|
217
|
+
},
|
|
218
|
+
transport: {
|
|
219
|
+
type: "string",
|
|
220
|
+
enum: ["relay_tunnel", "feishu_platform_session"],
|
|
221
|
+
},
|
|
217
222
|
connected_at: IsoDateTimeStringSchema,
|
|
218
223
|
},
|
|
219
224
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { requireRelaySessionContext, TRUSTED_RELAY_METADATA_REQUEST_HEADER, } from "../../../session/relay-session-context.js";
|
|
1
|
+
import { readFeishuPlatformSessionContext, readRelaySessionContext, requireFeishuPlatformSessionContext, requireRelaySessionContext, TRUSTED_RELAY_METADATA_REQUEST_HEADER, } from "../../../session/relay-session-context.js";
|
|
2
2
|
import { HostProjectForbiddenError, HostProjectStoreUnavailableError } from "./errors.js";
|
|
3
3
|
import { headerToString } from "./headers.js";
|
|
4
4
|
function readTrustedMetadata(request, store) {
|
|
@@ -9,8 +9,40 @@ function readTrustedMetadata(request, store) {
|
|
|
9
9
|
return store.consume(requestId);
|
|
10
10
|
}
|
|
11
11
|
export function requireHostProjectSession(request, options) {
|
|
12
|
-
const
|
|
12
|
+
const surface = options.surfaceProfile?.kind ?? "standalone";
|
|
13
|
+
const metadata = readTrustedMetadata(request, options.trustedMetadataStore);
|
|
13
14
|
const relayState = options.relay.getState();
|
|
15
|
+
if (surface === "feishu") {
|
|
16
|
+
if (readRelaySessionContext(metadata).kind === "present") {
|
|
17
|
+
throw new HostProjectForbiddenError();
|
|
18
|
+
}
|
|
19
|
+
const context = requireFeishuPlatformSessionContext(metadata);
|
|
20
|
+
if (relayState.relay_project_ref !== undefined &&
|
|
21
|
+
context.membership.relay_project_ref !== relayState.relay_project_ref) {
|
|
22
|
+
throw new HostProjectForbiddenError();
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
account: {
|
|
26
|
+
account_ref: context.account_ref,
|
|
27
|
+
display_name: context.display_name,
|
|
28
|
+
avatar: context.avatar,
|
|
29
|
+
},
|
|
30
|
+
membership: {
|
|
31
|
+
label: context.membership.label,
|
|
32
|
+
relay_project_ref: context.membership.relay_project_ref,
|
|
33
|
+
joined_at: context.membership.joined_at,
|
|
34
|
+
},
|
|
35
|
+
client_session: {
|
|
36
|
+
client_session_id: context.platform_session_ref,
|
|
37
|
+
transport: "feishu_platform_session",
|
|
38
|
+
connected_at: context.platform_session_created_at,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (readFeishuPlatformSessionContext(metadata).kind === "present") {
|
|
43
|
+
throw new HostProjectForbiddenError();
|
|
44
|
+
}
|
|
45
|
+
const context = requireRelaySessionContext(metadata);
|
|
14
46
|
if (relayState.relay_project_ref !== undefined &&
|
|
15
47
|
context.membership.relay_project_ref !== relayState.relay_project_ref) {
|
|
16
48
|
throw new HostProjectForbiddenError();
|
|
@@ -9,6 +9,7 @@ import type { TrustedRelaySessionMetadataStore } from "../../../session/relay-se
|
|
|
9
9
|
import type { WorkspaceEventBus } from "../../workspace-events.js";
|
|
10
10
|
import type { HOST_MAINLINE_BRANCH } from "./constants.js";
|
|
11
11
|
import type { GetProviderModelsResponse, ProviderUsageProjection, RelayUploadProjection, UpdateProviderDefaultModelDisposition, UpdateProviderDefaultModelPayload } from "@tutti/shared/schemas/api";
|
|
12
|
+
import type { ProjectSurfaceProfile } from "@tutti/shared/domain";
|
|
12
13
|
export type ResolvedStagedUpload = {
|
|
13
14
|
upload: RelayUploadProjection;
|
|
14
15
|
get: {
|
|
@@ -82,6 +83,7 @@ export type HostProviderModelService = {
|
|
|
82
83
|
}>;
|
|
83
84
|
};
|
|
84
85
|
export type HostProjectApiRouteOptions = {
|
|
86
|
+
surfaceProfile?: ProjectSurfaceProfile;
|
|
85
87
|
artifactPreview?: Omit<ArtifactPreviewManagerOptions, "onStatusChange">;
|
|
86
88
|
artifactPreviewManager?: ArtifactPreviewManager;
|
|
87
89
|
project: {
|
|
@@ -134,7 +136,7 @@ export type HostSessionProjection = {
|
|
|
134
136
|
};
|
|
135
137
|
client_session: {
|
|
136
138
|
client_session_id: string;
|
|
137
|
-
transport: "relay_tunnel";
|
|
139
|
+
transport: "relay_tunnel" | "feishu_platform_session";
|
|
138
140
|
connected_at: string;
|
|
139
141
|
};
|
|
140
142
|
};
|
|
@@ -76,13 +76,19 @@ export function buildBootstrapSnapshots(options, eventsNow, session) {
|
|
|
76
76
|
if (options.store === undefined) {
|
|
77
77
|
return {};
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
main_chat: readMainChatMessageWindow(options.store.db),
|
|
79
|
+
const sharedSnapshots = {
|
|
81
80
|
scratchpad: readScratchpadProjection(options.store.db),
|
|
82
81
|
worklist: readWorklistProjection(options.store.db),
|
|
83
82
|
active_clarification: readActiveClarificationProjection(options.store.db),
|
|
84
83
|
active_approval: options.approvalManager?.getActiveApproval() ?? { state: "none" },
|
|
85
84
|
execution_status: options.controlPlane?.getExecutionStatus() ?? createIdleExecutionStatusProjection(eventsNow),
|
|
85
|
+
};
|
|
86
|
+
if ((options.surfaceProfile?.kind ?? "standalone") === "feishu") {
|
|
87
|
+
return sharedSnapshots;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
main_chat: readMainChatMessageWindow(options.store.db),
|
|
91
|
+
...sharedSnapshots,
|
|
86
92
|
read_state: readReadStateSummary(options.store.db, {
|
|
87
93
|
account_ref: session.account.account_ref,
|
|
88
94
|
session_created_at: session.client_session.connected_at,
|
|
@@ -69,7 +69,9 @@ export async function restorePackageUpdateHosts(options) {
|
|
|
69
69
|
failed.push(projectId);
|
|
70
70
|
continue;
|
|
71
71
|
}
|
|
72
|
-
spawnDetachedHost({
|
|
72
|
+
const startup = spawnDetachedHost({
|
|
73
|
+
tuttiHome: options.tuttiHome,
|
|
74
|
+
projectId,
|
|
73
75
|
workspaceRoot: project.workspace_root,
|
|
74
76
|
env: { ...options.env, TUTTI_HOME: options.tuttiHome },
|
|
75
77
|
inheritProcessEnv: false,
|
|
@@ -79,6 +81,7 @@ export async function restorePackageUpdateHosts(options) {
|
|
|
79
81
|
projectId,
|
|
80
82
|
workspaceRoot: project.workspace_root,
|
|
81
83
|
inviteMode: "preserve",
|
|
84
|
+
startupAttemptRef: startup.startup_attempt_ref,
|
|
82
85
|
...(options.fetchImpl === undefined ? {} : { fetchImpl: options.fetchImpl }),
|
|
83
86
|
});
|
|
84
87
|
restored.push(projectId);
|