@xfey/tutti 0.1.113 → 0.1.115

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 (48) hide show
  1. package/dist/artifact-feedback/index.d.ts +1 -3
  2. package/dist/artifact-feedback/index.js +1 -15
  3. package/dist/chat-assistant/index.js +1 -1
  4. package/dist/collaboration-ingestion/external-source.d.ts +3 -0
  5. package/dist/collaboration-ingestion/external-source.js +33 -7
  6. package/dist/collaboration-ingestion/reply-context.d.ts +10 -0
  7. package/dist/collaboration-ingestion/reply-context.js +43 -0
  8. package/dist/collaboration-state/clarification-snapshot.d.ts +11 -0
  9. package/dist/collaboration-state/message-context.d.ts +5 -0
  10. package/dist/collaboration-state/message-context.js +28 -0
  11. package/dist/control-plane/scratchpad-source-messages.js +1 -1
  12. package/dist/control-plane/task-source-context.js +1 -1
  13. package/dist/reference-access/message-context.js +3 -0
  14. package/dist/server-shell/cli/host-server-runtime.js +1 -0
  15. package/dist/server-shell/cli/relay-registration.js +1 -0
  16. package/dist/server-shell/http/routes/agent-context-messages-routes.js +2 -1
  17. package/dist/server-shell/http/routes/agent-context-skills-routes.js +2 -1
  18. package/dist/server-shell/http/routes/project-api/openapi-skills-routes.d.ts +23 -0
  19. package/dist/server-shell/http/routes/project-api/openapi-skills-routes.js +9 -1
  20. package/dist/server-shell/http/routes/project-api/openapi.d.ts +22 -0
  21. package/dist/server-shell/http/routes/project-api/project-timeline-projection.js +27 -33
  22. package/dist/server-shell/http/routes/project-api/skills-helpers.js +9 -0
  23. package/dist/server-shell/http/routes/project-api/skills-routes.js +8 -4
  24. package/dist/server-shell/http/validation.js +1 -0
  25. package/dist/skills/constants.d.ts +5 -0
  26. package/dist/skills/constants.js +6 -0
  27. package/dist/skills/errors.d.ts +1 -1
  28. package/dist/skills/file-reader.d.ts +14 -0
  29. package/dist/skills/file-reader.js +123 -0
  30. package/dist/skills/index.d.ts +5 -2
  31. package/dist/skills/index.js +36 -41
  32. package/dist/skills/metadata.d.ts +2 -0
  33. package/dist/skills/metadata.js +10 -1
  34. package/dist/skills/zip-import.js +2 -2
  35. package/node_modules/@tutti/relay-client/dist/host-control.d.ts +1 -0
  36. package/node_modules/@tutti/relay-client/dist/host-control.js +3 -0
  37. package/node_modules/@tutti/shared/dist/schemas/api/clarifications.d.ts +11 -0
  38. package/node_modules/@tutti/shared/dist/schemas/api/messages.d.ts +55 -0
  39. package/node_modules/@tutti/shared/dist/schemas/api/messages.js +23 -0
  40. package/node_modules/@tutti/shared/dist/schemas/api/primitives.d.ts +2 -2
  41. package/node_modules/@tutti/shared/dist/schemas/api/primitives.js +1 -0
  42. package/node_modules/@tutti/shared/dist/schemas/api/viewer-reference.d.ts +11 -0
  43. package/package.json +1 -1
  44. package/web/assets/{homepage-motion-scene-BwdH6Iss.js → homepage-motion-scene-BkZq6XoY.js} +1 -1
  45. package/web/assets/{index-DvfZ57Nl.css → index-C9grZQCJ.css} +1 -1
  46. package/web/assets/index-DZS21yn3.js +69 -0
  47. package/web/index.html +2 -2
  48. package/web/assets/index-B29RuNsd.js +0 -69
@@ -0,0 +1,14 @@
1
+ export declare function skillReadLimitExceeded(): never;
2
+ /** Read from one checked descriptor; never follow a SKILL.md symlink or block on a FIFO. */
3
+ export declare function readSkillFile(input: {
4
+ root: string;
5
+ name: string;
6
+ maxBytes: number;
7
+ metadataOnly?: boolean;
8
+ }): {
9
+ markdown: string;
10
+ updatedAt: string;
11
+ };
12
+ /** Bound enumeration before collecting names; a limit never returns a partial list. */
13
+ export declare function listSkillDirectories(root: string, maxEntries?: number): string[];
14
+ //# sourceMappingURL=file-reader.d.ts.map
@@ -0,0 +1,123 @@
1
+ import { closeSync, constants, fstatSync, lstatSync, openSync, opendirSync, readSync, realpathSync, } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { SKILL_MD_FILE_NAME } from "./constants.js";
4
+ import { SkillServiceError } from "./errors.js";
5
+ import { decodeSkillMarkdown, isValidSkillName } from "./metadata.js";
6
+ function unsafePath() {
7
+ throw new SkillServiceError("validation_failed", "Skill path is not a regular project skill");
8
+ }
9
+ export function skillReadLimitExceeded() {
10
+ throw new SkillServiceError("read_limit_exceeded", "Skill read exceeds the supported limit");
11
+ }
12
+ function mapReadError(error) {
13
+ if (error instanceof SkillServiceError)
14
+ throw error;
15
+ const code = error.code;
16
+ if (code === "ENOENT" || code === "ENOTDIR") {
17
+ throw new SkillServiceError("skill_not_found", "Skill does not exist");
18
+ }
19
+ throw new SkillServiceError("filesystem_error", "Skill could not be read");
20
+ }
21
+ function realDirectory(path) {
22
+ if (!lstatSync(path).isDirectory())
23
+ unsafePath();
24
+ return realpathSync(path);
25
+ }
26
+ function resolveSkillFile(root, name) {
27
+ const realRoot = realDirectory(resolve(root));
28
+ const directory = join(realRoot, name);
29
+ if (realDirectory(directory) !== directory)
30
+ unsafePath();
31
+ const file = join(directory, SKILL_MD_FILE_NAME);
32
+ if (!lstatSync(file).isFile() || realpathSync(file) !== file)
33
+ unsafePath();
34
+ return file;
35
+ }
36
+ function sameFile(left, right) {
37
+ return (left.dev === right.dev &&
38
+ left.ino === right.ino &&
39
+ left.size === right.size &&
40
+ left.mtimeMs === right.mtimeMs &&
41
+ left.ctimeMs === right.ctimeMs);
42
+ }
43
+ /** Read from one checked descriptor; never follow a SKILL.md symlink or block on a FIFO. */
44
+ export function readSkillFile(input) {
45
+ if (!isValidSkillName(input.name)) {
46
+ throw new SkillServiceError("invalid_skill_name", "Skill name is invalid");
47
+ }
48
+ let fd;
49
+ try {
50
+ const file = resolveSkillFile(input.root, input.name);
51
+ fd = openSync(file, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
52
+ const before = fstatSync(fd);
53
+ if (!before.isFile() || !sameFile(before, lstatSync(file)))
54
+ unsafePath();
55
+ if (!input.metadataOnly && before.size > input.maxBytes)
56
+ skillReadLimitExceeded();
57
+ const buffer = Buffer.alloc(Math.min(before.size, input.maxBytes) + 1);
58
+ let length = 0;
59
+ while (length < buffer.length) {
60
+ const read = readSync(fd, buffer, length, buffer.length - length, length);
61
+ if (read === 0)
62
+ break;
63
+ length += read;
64
+ }
65
+ if (!sameFile(before, fstatSync(fd)) ||
66
+ resolveSkillFile(input.root, input.name) !== file ||
67
+ !sameFile(before, lstatSync(file))) {
68
+ throw new SkillServiceError("filesystem_error", "Skill changed while being read");
69
+ }
70
+ const bytes = buffer.subarray(0, length);
71
+ const text = decodeSkillMarkdown(bytes, input.metadataOnly === true && before.size > length);
72
+ if (input.metadataOnly) {
73
+ // Frontmatter syntax stays owned by metadata.ts. Only its bounded prefix is decoded.
74
+ const prefix = text.replace(/\r\n/gu, "\n");
75
+ const end = prefix.startsWith("---\n") ? prefix.indexOf("\n---", 4) : -1;
76
+ if (end !== -1) {
77
+ const metadata = prefix.slice(0, end + 4);
78
+ if (Buffer.byteLength(metadata) > input.maxBytes)
79
+ skillReadLimitExceeded();
80
+ return { markdown: metadata, updatedAt: before.mtime.toISOString() };
81
+ }
82
+ }
83
+ if (length > input.maxBytes)
84
+ skillReadLimitExceeded();
85
+ return { markdown: text, updatedAt: before.mtime.toISOString() };
86
+ }
87
+ catch (error) {
88
+ return mapReadError(error);
89
+ }
90
+ finally {
91
+ if (fd !== undefined)
92
+ closeSync(fd);
93
+ }
94
+ }
95
+ /** Bound enumeration before collecting names; a limit never returns a partial list. */
96
+ export function listSkillDirectories(root, maxEntries = Infinity) {
97
+ try {
98
+ const realRoot = realDirectory(resolve(root));
99
+ const directory = opendirSync(realRoot);
100
+ const names = [];
101
+ let count = 0;
102
+ try {
103
+ for (let entry = directory.readSync(); entry !== null; entry = directory.readSync()) {
104
+ if (++count > maxEntries)
105
+ skillReadLimitExceeded();
106
+ if (entry.isDirectory() && isValidSkillName(entry.name))
107
+ names.push(entry.name);
108
+ }
109
+ }
110
+ finally {
111
+ directory.closeSync();
112
+ }
113
+ if (realDirectory(resolve(root)) !== realRoot)
114
+ unsafePath();
115
+ return names.sort();
116
+ }
117
+ catch (error) {
118
+ if (error.code === "ENOENT")
119
+ return [];
120
+ return mapReadError(error);
121
+ }
122
+ }
123
+ //# sourceMappingURL=file-reader.js.map
@@ -26,9 +26,12 @@ export type UserSkillImportResult = {
26
26
  disposition: UserSkillImportDisposition;
27
27
  skill: SkillDetailProjection;
28
28
  };
29
+ export type UserSkillReadOptions = {
30
+ mode?: "full" | "preview";
31
+ };
29
32
  export declare function getProjectUserSkillsRoot(tuttiHome: string, projectId: ProjectId): string;
30
- export declare function listUserSkills(userSkillsRoot: string): SkillProjection[];
31
- export declare function readUserSkill(userSkillsRoot: string, skillName: string): SkillDetailProjection;
33
+ export declare function listUserSkills(userSkillsRoot: string, options?: UserSkillReadOptions): SkillProjection[];
34
+ export declare function readUserSkill(userSkillsRoot: string, skillName: string, options?: UserSkillReadOptions): SkillDetailProjection;
32
35
  export declare function importUserSkillZip(options: {
33
36
  userSkillsRoot: string;
34
37
  zipBuffer: Buffer;
@@ -1,9 +1,10 @@
1
- import { existsSync, mkdtempSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, } from "node:fs";
1
+ import { existsSync, mkdtempSync, mkdirSync, renameSync, rmSync, statSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join, resolve } from "node:path";
4
- import { SKILL_MD_FILE_NAME, USER_SKILLS_DIRECTORY_NAME } from "./constants.js";
4
+ import { MAX_SKILL_FILE_BYTES, MAX_SKILL_PREVIEW_BYTES, MAX_SKILL_PREVIEW_METADATA_BYTES, MAX_SKILL_PREVIEW_SCAN_ENTRIES, MAX_SKILL_PREVIEW_ITEMS, MAX_SKILL_PREVIEW_LIST_BYTES, USER_SKILLS_DIRECTORY_NAME, } from "./constants.js";
5
5
  import { SkillServiceError } from "./errors.js";
6
- import { isValidSkillName, parseSkillMarkdown, } from "./metadata.js";
6
+ import { listSkillDirectories, readSkillFile, skillReadLimitExceeded } from "./file-reader.js";
7
+ import { isValidSkillName, parseSkillMarkdown } from "./metadata.js";
7
8
  import { prepareUserSkillZipImport, writeCandidateFiles, } from "./zip-import.js";
8
9
  export { MAX_SKILL_DIRECTORY_DEPTH, MAX_SKILL_FILE_BYTES, MAX_SKILL_FILE_COUNT, MAX_SKILL_TOTAL_UNCOMPRESSED_BYTES, MAX_SKILL_ZIP_BYTES, SKILL_MD_FILE_NAME, USER_SKILLS_DIRECTORY_NAME, } from "./constants.js";
9
10
  export { SkillServiceError } from "./errors.js";
@@ -30,17 +31,6 @@ function skillDirectory(userSkillsRoot, skillName) {
30
31
  ensureInside(userSkillsRoot, directory);
31
32
  return directory;
32
33
  }
33
- function readSkillMarkdown(filePath) {
34
- let skillMd;
35
- try {
36
- skillMd = readFileSync(filePath, "utf8");
37
- }
38
- catch {
39
- throw new SkillServiceError("skill_not_found", "Skill does not exist");
40
- }
41
- const metadata = parseSkillMarkdown(skillMd);
42
- return { ...metadata, skill_md: skillMd };
43
- }
44
34
  function toSkillProjection(options) {
45
35
  return {
46
36
  name: options.metadata.name,
@@ -53,53 +43,58 @@ function toSkillProjection(options) {
53
43
  ...(options.updatedAt === undefined ? {} : { updated_at: options.updatedAt }),
54
44
  };
55
45
  }
56
- function readSkillProjection(directory) {
57
- const skillMdPath = join(directory, SKILL_MD_FILE_NAME);
58
- const parsed = readSkillMarkdown(skillMdPath);
59
- const stat = statSync(skillMdPath);
46
+ function readSkillProjection(root, name, preview) {
47
+ const file = readSkillFile({
48
+ root,
49
+ name,
50
+ maxBytes: preview ? MAX_SKILL_PREVIEW_METADATA_BYTES : MAX_SKILL_FILE_BYTES,
51
+ metadataOnly: preview,
52
+ });
60
53
  return toSkillProjection({
61
- metadata: parsed,
62
- updatedAt: stat.mtime.toISOString(),
54
+ metadata: parseSkillMarkdown(file.markdown),
55
+ updatedAt: file.updatedAt,
63
56
  });
64
57
  }
65
- export function listUserSkills(userSkillsRoot) {
66
- if (!existsSync(userSkillsRoot)) {
67
- return [];
68
- }
58
+ export function listUserSkills(userSkillsRoot, options = {}) {
59
+ const preview = options.mode === "preview";
69
60
  const items = [];
70
- for (const entry of readdirSync(userSkillsRoot, { withFileTypes: true })) {
71
- if (!entry.isDirectory() || !isValidSkillName(entry.name)) {
72
- continue;
73
- }
61
+ let responseBytes = Buffer.byteLength('{"items":[]}');
62
+ for (const name of listSkillDirectories(userSkillsRoot, preview ? MAX_SKILL_PREVIEW_SCAN_ENTRIES : undefined)) {
74
63
  try {
75
- const projection = readSkillProjection(join(userSkillsRoot, entry.name));
76
- if (projection.name === entry.name) {
64
+ const projection = readSkillProjection(userSkillsRoot, name, preview);
65
+ if (projection.name === name) {
66
+ responseBytes += Buffer.byteLength(JSON.stringify(projection)) + 1;
67
+ if (preview &&
68
+ (items.length >= MAX_SKILL_PREVIEW_ITEMS || responseBytes > MAX_SKILL_PREVIEW_LIST_BYTES)) {
69
+ skillReadLimitExceeded();
70
+ }
77
71
  items.push(projection);
78
72
  }
79
73
  }
80
- catch {
74
+ catch (error) {
75
+ if (preview && error instanceof SkillServiceError && error.code === "read_limit_exceeded")
76
+ throw error;
81
77
  // Keep the management surface available even if a stale local directory is malformed.
82
78
  }
83
79
  }
84
80
  return items.sort((left, right) => left.name.localeCompare(right.name));
85
81
  }
86
- export function readUserSkill(userSkillsRoot, skillName) {
87
- const directory = skillDirectory(userSkillsRoot, skillName);
88
- const skillMdPath = join(directory, SKILL_MD_FILE_NAME);
89
- if (!existsSync(skillMdPath)) {
90
- throw new SkillServiceError("skill_not_found", "Skill does not exist");
91
- }
92
- const parsed = readSkillMarkdown(skillMdPath);
82
+ export function readUserSkill(userSkillsRoot, skillName, options = {}) {
83
+ const file = readSkillFile({
84
+ root: userSkillsRoot,
85
+ name: skillName,
86
+ maxBytes: options.mode === "preview" ? MAX_SKILL_PREVIEW_BYTES : MAX_SKILL_FILE_BYTES,
87
+ });
88
+ const parsed = parseSkillMarkdown(file.markdown);
93
89
  if (parsed.name !== skillName) {
94
90
  throw new SkillServiceError("validation_failed", "Skill metadata is invalid");
95
91
  }
96
- const stat = statSync(skillMdPath);
97
92
  return {
98
93
  ...toSkillProjection({
99
94
  metadata: parsed,
100
- updatedAt: stat.mtime.toISOString(),
95
+ updatedAt: file.updatedAt,
101
96
  }),
102
- skill_md: parsed.skill_md,
97
+ skill_md: file.markdown,
103
98
  };
104
99
  }
105
100
  export async function importUserSkillZip(options) {
@@ -4,5 +4,7 @@ export type ParsedSkillMarkdown = {
4
4
  short_description?: string;
5
5
  };
6
6
  export declare function isValidSkillName(value: string): boolean;
7
+ /** Keep import preflight and runtime reads consistent; partial applies only to bounded prefixes. */
8
+ export declare function decodeSkillMarkdown(bytes: Uint8Array, partial?: boolean): string;
7
9
  export declare function parseSkillMarkdown(skillMd: string): ParsedSkillMarkdown;
8
10
  //# sourceMappingURL=metadata.d.ts.map
@@ -1,7 +1,16 @@
1
1
  import { SkillServiceError } from "./errors.js";
2
2
  const SKILL_NAME_PATTERN = /^[a-z0-9_-]+$/u;
3
3
  export function isValidSkillName(value) {
4
- return SKILL_NAME_PATTERN.test(value);
4
+ return value.length <= 96 && SKILL_NAME_PATTERN.test(value);
5
+ }
6
+ /** Keep import preflight and runtime reads consistent; partial applies only to bounded prefixes. */
7
+ export function decodeSkillMarkdown(bytes, partial = false) {
8
+ try {
9
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes, { stream: partial });
10
+ }
11
+ catch {
12
+ throw new SkillServiceError("validation_failed", "Skill text is not valid UTF-8");
13
+ }
5
14
  }
6
15
  export function parseSkillMarkdown(skillMd) {
7
16
  const frontmatter = extractFrontmatter(skillMd);
@@ -3,7 +3,7 @@ import { dirname, join, resolve } from "node:path";
3
3
  import * as yauzl from "yauzl";
4
4
  import { MAX_SKILL_DIRECTORY_DEPTH, MAX_SKILL_FILE_BYTES, MAX_SKILL_FILE_COUNT, MAX_SKILL_TOTAL_UNCOMPRESSED_BYTES, MAX_SKILL_ZIP_BYTES, SKILL_MD_FILE_NAME, } from "./constants.js";
5
5
  import { SkillServiceError } from "./errors.js";
6
- import { isValidSkillName, parseSkillMarkdown } from "./metadata.js";
6
+ import { decodeSkillMarkdown, isValidSkillName, parseSkillMarkdown, } from "./metadata.js";
7
7
  const ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
8
8
  const UNIX_FILE_TYPE_MASK = 0o170000;
9
9
  const UNIX_REGULAR_FILE = 0o100000;
@@ -209,7 +209,7 @@ function buildImportCandidate(entries) {
209
209
  if (skillMd === undefined) {
210
210
  throw new SkillServiceError("validation_failed", "SKILL.md is missing");
211
211
  }
212
- const metadata = parseSkillMarkdown(skillMd.data.toString("utf8"));
212
+ const metadata = parseSkillMarkdown(decodeSkillMarkdown(skillMd.data));
213
213
  if (rootPrefix !== "" && rootPrefix !== metadata.name) {
214
214
  throw new SkillServiceError("validation_failed", "Skill root does not match skill name");
215
215
  }
@@ -46,6 +46,7 @@ export type RegisterRelayHostConnectionPayload = {
46
46
  integration_source_ingestion_v1?: boolean;
47
47
  integration_development_bot_v1?: boolean;
48
48
  integration_clarification_v1?: boolean;
49
+ feishu_supporting_reads_v1?: boolean;
49
50
  integration_external_references_v1?: boolean;
50
51
  integration_attachment_ingestion_v1?: boolean;
51
52
  integration_managed_reference_ingestion_v1?: boolean;
@@ -68,6 +68,9 @@ function createRegisterPayload(options) {
68
68
  ...(capabilities.integration_clarification_v1 === true
69
69
  ? { integration_clarification_v1: true }
70
70
  : {}),
71
+ ...(capabilities.feishu_supporting_reads_v1 === true
72
+ ? { feishu_supporting_reads_v1: true }
73
+ : {}),
71
74
  },
72
75
  },
73
76
  };
@@ -511,6 +511,17 @@ export declare const SendClarificationRoundMessageResultSchema: import("@sinclai
511
511
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
512
512
  body: import("@sinclair/typebox").TString;
513
513
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
514
+ reply_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
515
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
516
+ message_id: import("@sinclair/typebox").TString;
517
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
518
+ text: import("@sinclair/typebox").TString;
519
+ truncated: import("@sinclair/typebox").TBoolean;
520
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
521
+ }>, import("@sinclair/typebox").TObject<{
522
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
523
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
524
+ }>]>>;
514
525
  development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
515
526
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
516
527
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -132,7 +132,29 @@ export declare const ArtifactPreviewRefSchema: import("@sinclair/typebox").TObje
132
132
  task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
133
133
  run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
134
134
  }>;
135
+ export declare const MessageReplyContextSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
136
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
137
+ message_id: import("@sinclair/typebox").TString;
138
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
139
+ text: import("@sinclair/typebox").TString;
140
+ truncated: import("@sinclair/typebox").TBoolean;
141
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
142
+ }>, import("@sinclair/typebox").TObject<{
143
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
144
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
145
+ }>]>;
135
146
  export declare const MessageRefsSchema: import("@sinclair/typebox").TObject<{
147
+ reply_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
148
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
149
+ message_id: import("@sinclair/typebox").TString;
150
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
151
+ text: import("@sinclair/typebox").TString;
152
+ truncated: import("@sinclair/typebox").TBoolean;
153
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
154
+ }>, import("@sinclair/typebox").TObject<{
155
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
156
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
157
+ }>]>>;
136
158
  development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
137
159
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
138
160
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -345,6 +367,17 @@ export declare const MessageProjectionSchema: import("@sinclair/typebox").TObjec
345
367
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
346
368
  body: import("@sinclair/typebox").TString;
347
369
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
370
+ reply_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
371
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
372
+ message_id: import("@sinclair/typebox").TString;
373
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
374
+ text: import("@sinclair/typebox").TString;
375
+ truncated: import("@sinclair/typebox").TBoolean;
376
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
377
+ }>, import("@sinclair/typebox").TObject<{
378
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
379
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
380
+ }>]>>;
348
381
  development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
349
382
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
350
383
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -676,6 +709,17 @@ export declare const SendMainChatMessageResultSchema: import("@sinclair/typebox"
676
709
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
677
710
  body: import("@sinclair/typebox").TString;
678
711
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
712
+ reply_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
713
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
714
+ message_id: import("@sinclair/typebox").TString;
715
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
716
+ text: import("@sinclair/typebox").TString;
717
+ truncated: import("@sinclair/typebox").TBoolean;
718
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
719
+ }>, import("@sinclair/typebox").TObject<{
720
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
721
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
722
+ }>]>>;
679
723
  development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
680
724
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
681
725
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -909,6 +953,17 @@ export declare const MessageCreatedEventPayloadSchema: import("@sinclair/typebox
909
953
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
910
954
  body: import("@sinclair/typebox").TString;
911
955
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
956
+ reply_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
957
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
958
+ message_id: import("@sinclair/typebox").TString;
959
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
960
+ text: import("@sinclair/typebox").TString;
961
+ truncated: import("@sinclair/typebox").TBoolean;
962
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
963
+ }>, import("@sinclair/typebox").TObject<{
964
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
965
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
966
+ }>]>>;
912
967
  development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
913
968
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
914
969
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -124,7 +124,30 @@ export const ArtifactPreviewRefSchema = Type.Object({
124
124
  task_id: Type.Optional(TaskIdSchema),
125
125
  run_result_id: Type.Optional(RunResultIdSchema),
126
126
  }, { additionalProperties: false });
127
+ export const MessageReplyContextSchema = Type.Union([
128
+ Type.Object({
129
+ status: Type.Literal("resolved"),
130
+ message_id: MessageIdSchema,
131
+ role: Type.Union([
132
+ Type.Literal("human"),
133
+ Type.Literal("tutti"),
134
+ Type.Literal("operator"),
135
+ Type.Literal("system"),
136
+ ]),
137
+ text: Type.String({ maxLength: 2_000 }),
138
+ truncated: Type.Boolean(),
139
+ external_reference_sources: Type.Array(ExternalReferenceRefSchema, {
140
+ maxItems: 16,
141
+ uniqueItems: true,
142
+ }),
143
+ }, { additionalProperties: false }),
144
+ Type.Object({
145
+ status: Type.Literal("unavailable"),
146
+ reason_code: Type.Literal("parent_not_observed_in_binding"),
147
+ }, { additionalProperties: false }),
148
+ ]);
127
149
  export const MessageRefsSchema = Type.Object({
150
+ reply_context: Type.Optional(MessageReplyContextSchema),
128
151
  development_operator: Type.Optional(Type.Literal(true)),
129
152
  external_reference_reads: Type.Optional(Type.Array(ExternalReferenceRefSchema, { minItems: 1, maxItems: 16, uniqueItems: true })),
130
153
  external_references: Type.Optional(Type.Array(ExternalReferenceDescriptorSchema, { minItems: 1, maxItems: 16 })),
@@ -72,10 +72,10 @@ export declare const InterruptedCommandDispositionSchema: import("@sinclair/type
72
72
  export declare function commandEnvelopeSchema<TPayload extends TSchema>(payload: TPayload): TSchema;
73
73
  export declare function commandResponseSchema<TDisposition extends TSchema>(disposition: TDisposition): TSchema;
74
74
  export declare function commandResponseWithResultSchema<TDisposition extends TSchema, TResult extends TSchema>(disposition: TDisposition, result: TResult): TSchema;
75
- export declare const ApiErrorCodeSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"bad_request">, import("@sinclair/typebox").TLiteral<"unauthorized">, import("@sinclair/typebox").TLiteral<"forbidden">, import("@sinclair/typebox").TLiteral<"not_found">, import("@sinclair/typebox").TLiteral<"conflict">, import("@sinclair/typebox").TLiteral<"validation_failed">, import("@sinclair/typebox").TLiteral<"provider_not_configured">, import("@sinclair/typebox").TLiteral<"provider_auth_invalid">, import("@sinclair/typebox").TLiteral<"provider_quota_or_billing_required">, import("@sinclair/typebox").TLiteral<"provider_rate_limited">, import("@sinclair/typebox").TLiteral<"provider_model_unavailable">, import("@sinclair/typebox").TLiteral<"provider_network_error">, import("@sinclair/typebox").TLiteral<"relay_session_invalid">, import("@sinclair/typebox").TLiteral<"project_membership_required">, import("@sinclair/typebox").TLiteral<"command_replay_mismatch">, import("@sinclair/typebox").TLiteral<"repo_snapshot_unavailable">, import("@sinclair/typebox").TLiteral<"host_unavailable">, import("@sinclair/typebox").TLiteral<"internal_error">]>;
75
+ export declare const ApiErrorCodeSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"bad_request">, import("@sinclair/typebox").TLiteral<"unauthorized">, import("@sinclair/typebox").TLiteral<"forbidden">, import("@sinclair/typebox").TLiteral<"not_found">, import("@sinclair/typebox").TLiteral<"conflict">, import("@sinclair/typebox").TLiteral<"validation_failed">, import("@sinclair/typebox").TLiteral<"provider_not_configured">, import("@sinclair/typebox").TLiteral<"provider_auth_invalid">, import("@sinclair/typebox").TLiteral<"provider_quota_or_billing_required">, import("@sinclair/typebox").TLiteral<"provider_rate_limited">, import("@sinclair/typebox").TLiteral<"provider_model_unavailable">, import("@sinclair/typebox").TLiteral<"provider_network_error">, import("@sinclair/typebox").TLiteral<"relay_session_invalid">, import("@sinclair/typebox").TLiteral<"project_membership_required">, import("@sinclair/typebox").TLiteral<"command_replay_mismatch">, import("@sinclair/typebox").TLiteral<"repo_snapshot_unavailable">, import("@sinclair/typebox").TLiteral<"host_unavailable">, import("@sinclair/typebox").TLiteral<"skill_read_limit_exceeded">, import("@sinclair/typebox").TLiteral<"internal_error">]>;
76
76
  export declare const ApiErrorResponseSchema: import("@sinclair/typebox").TObject<{
77
77
  error: import("@sinclair/typebox").TObject<{
78
- code: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"bad_request">, import("@sinclair/typebox").TLiteral<"unauthorized">, import("@sinclair/typebox").TLiteral<"forbidden">, import("@sinclair/typebox").TLiteral<"not_found">, import("@sinclair/typebox").TLiteral<"conflict">, import("@sinclair/typebox").TLiteral<"validation_failed">, import("@sinclair/typebox").TLiteral<"provider_not_configured">, import("@sinclair/typebox").TLiteral<"provider_auth_invalid">, import("@sinclair/typebox").TLiteral<"provider_quota_or_billing_required">, import("@sinclair/typebox").TLiteral<"provider_rate_limited">, import("@sinclair/typebox").TLiteral<"provider_model_unavailable">, import("@sinclair/typebox").TLiteral<"provider_network_error">, import("@sinclair/typebox").TLiteral<"relay_session_invalid">, import("@sinclair/typebox").TLiteral<"project_membership_required">, import("@sinclair/typebox").TLiteral<"command_replay_mismatch">, import("@sinclair/typebox").TLiteral<"repo_snapshot_unavailable">, import("@sinclair/typebox").TLiteral<"host_unavailable">, import("@sinclair/typebox").TLiteral<"internal_error">]>;
78
+ code: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"bad_request">, import("@sinclair/typebox").TLiteral<"unauthorized">, import("@sinclair/typebox").TLiteral<"forbidden">, import("@sinclair/typebox").TLiteral<"not_found">, import("@sinclair/typebox").TLiteral<"conflict">, import("@sinclair/typebox").TLiteral<"validation_failed">, import("@sinclair/typebox").TLiteral<"provider_not_configured">, import("@sinclair/typebox").TLiteral<"provider_auth_invalid">, import("@sinclair/typebox").TLiteral<"provider_quota_or_billing_required">, import("@sinclair/typebox").TLiteral<"provider_rate_limited">, import("@sinclair/typebox").TLiteral<"provider_model_unavailable">, import("@sinclair/typebox").TLiteral<"provider_network_error">, import("@sinclair/typebox").TLiteral<"relay_session_invalid">, import("@sinclair/typebox").TLiteral<"project_membership_required">, import("@sinclair/typebox").TLiteral<"command_replay_mismatch">, import("@sinclair/typebox").TLiteral<"repo_snapshot_unavailable">, import("@sinclair/typebox").TLiteral<"host_unavailable">, import("@sinclair/typebox").TLiteral<"skill_read_limit_exceeded">, import("@sinclair/typebox").TLiteral<"internal_error">]>;
79
79
  message: import("@sinclair/typebox").TString;
80
80
  retryable: import("@sinclair/typebox").TBoolean;
81
81
  details: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
@@ -106,6 +106,7 @@ export const ApiErrorCodeSchema = Type.Union([
106
106
  Type.Literal("command_replay_mismatch"),
107
107
  Type.Literal("repo_snapshot_unavailable"),
108
108
  Type.Literal("host_unavailable"),
109
+ Type.Literal("skill_read_limit_exceeded"),
109
110
  Type.Literal("internal_error"),
110
111
  ]);
111
112
  export const ApiErrorResponseSchema = Type.Object({
@@ -400,6 +400,17 @@ export declare const UploadReferenceFileResultSchema: import("@sinclair/typebox"
400
400
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
401
401
  body: import("@sinclair/typebox").TString;
402
402
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
403
+ reply_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
404
+ status: import("@sinclair/typebox").TLiteral<"resolved">;
405
+ message_id: import("@sinclair/typebox").TString;
406
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"tutti">, import("@sinclair/typebox").TLiteral<"operator">, import("@sinclair/typebox").TLiteral<"system">]>;
407
+ text: import("@sinclair/typebox").TString;
408
+ truncated: import("@sinclair/typebox").TBoolean;
409
+ external_reference_sources: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
410
+ }>, import("@sinclair/typebox").TObject<{
411
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
412
+ reason_code: import("@sinclair/typebox").TLiteral<"parent_not_observed_in_binding">;
413
+ }>]>>;
403
414
  development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
404
415
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
405
416
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfey/tutti",
3
- "version": "0.1.113",
3
+ "version": "0.1.115",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",