@larkup/workspace-server 0.2.1 → 0.2.2
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/dist-types/app/api/chat/route.d.ts.map +1 -1
- package/dist-types/app/api/chat/tools.d.ts.map +1 -1
- package/dist-types/lib/chat/media-retrieval-routing.d.ts +2 -0
- package/dist-types/lib/chat/media-retrieval-routing.d.ts.map +1 -1
- package/dist-types/lib/chat/media-source-routing.d.ts +3 -0
- package/dist-types/lib/chat/media-source-routing.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/app/api/chat/route.ts +24 -1
- package/src/app/api/chat/tools.ts +4 -16
- package/src/lib/chat/media-retrieval-routing.ts +10 -0
- package/src/lib/chat/media-source-routing.ts +9 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/app/api/chat/route.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/app/api/chat/route.ts"],"names":[],"mappings":"AAkHA,eAAO,MAAM,WAAW,MAAM,CAAC;AAktB/B,wBAAsB,IAAI,CAAC,GAAG,EAAE,OAAO,qBAu7CtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../src/app/api/chat/tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../src/app/api/chat/tools.ts"],"names":[],"mappings":"AA+WA,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0I7F;AAyVD,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gGAAgG;IAChG,iBAAiB,CAAC,EAAE;QAClB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACtC,CAAC;IACF,oFAAoF;IACpF,wBAAwB,CAAC,EAAE;QACzB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACtC,CAAC;IACF,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;;;;;;GAumFA"}
|
|
@@ -10,5 +10,7 @@ export declare function leadingMediaAssetId(retrieval: {
|
|
|
10
10
|
}, activeAssetIds: ReadonlySet<string>, assetIdByDocumentId: ReadonlyMap<string, string>): string | undefined;
|
|
11
11
|
/** Read only an explicitly routed media source, never metadata on secondary search hits. */
|
|
12
12
|
export declare function explicitMediaEvidenceAssetId(value: unknown): string | null;
|
|
13
|
+
/** A deterministic gate before an answer model is allowed to compose prose. */
|
|
14
|
+
export declare function hasRetrievedSourceEvidence(value: unknown): boolean;
|
|
13
15
|
export {};
|
|
14
16
|
//# sourceMappingURL=media-retrieval-routing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-retrieval-routing.d.ts","sourceRoot":"","sources":["../../../src/lib/chat/media-retrieval-routing.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACvC,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,mBAAmB,CACjC,SAAS,EAAE;IAAE,IAAI,CAAC,EAAE,YAAY,EAAE,CAAA;CAAE,EACpC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,EACnC,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/C,MAAM,GAAG,SAAS,CASpB;AAED,4FAA4F;AAC5F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc1E"}
|
|
1
|
+
{"version":3,"file":"media-retrieval-routing.d.ts","sourceRoot":"","sources":["../../../src/lib/chat/media-retrieval-routing.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACvC,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,mBAAmB,CACjC,SAAS,EAAE;IAAE,IAAI,CAAC,EAAE,YAAY,EAAE,CAAA;CAAE,EACpC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,EACnC,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/C,MAAM,GAAG,SAAS,CASpB;AAED,4FAA4F;AAC5F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc1E;AAED,+EAA+E;AAC/E,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOlE"}
|
|
@@ -15,6 +15,9 @@ export declare function clearlyTitleMatchedMediaAsset<T extends RoutableMediaAss
|
|
|
15
15
|
* retrieval miss, but it must never pre-empt a document or tabular hit.
|
|
16
16
|
*/
|
|
17
17
|
export declare function explicitlySelectedMediaAsset<T extends RoutableMediaAsset>(query: string, assets: readonly T[]): T | undefined;
|
|
18
|
+
/** Recover media after a miss only when the user named the source clearly.
|
|
19
|
+
* A sole video is not evidence for every unrelated question. */
|
|
20
|
+
export declare function retrievalFallbackMediaAsset<T extends RoutableMediaAsset>(query: string, assets: readonly T[]): T | undefined;
|
|
18
21
|
/**
|
|
19
22
|
* Detect an explicitly named source that exists but is outside the Assistant
|
|
20
23
|
* source scope. A generic single-source fallback must not silently replace it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-source-routing.d.ts","sourceRoot":"","sources":["../../../src/lib/chat/media-source-routing.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,kBAAkB,EACxE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,CAAC,GAAG,SAAS,CAUf;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,SAAS,kBAAkB,EACvE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,CAAC,GAAG,SAAS,CAEf;AAED;;;;GAIG;AACH,wBAAgB,wCAAwC,CAAC,CAAC,SAAS,kBAAkB,EACnF,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,SAAS,CAAC,EAAE,EAC7B,SAAS,EAAE,SAAS,CAAC,EAAE,GACtB,CAAC,GAAG,SAAS,CAIf;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,kBAAkB,EACtE,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,CAAC,EACd,eAAe,EAAE,SAAS,CAAC,EAAE,WAG9B;AAED,wFAAwF;AACxF,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,kBAAkB,EACzB,cAAc,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;EAyBxB"}
|
|
1
|
+
{"version":3,"file":"media-source-routing.d.ts","sourceRoot":"","sources":["../../../src/lib/chat/media-source-routing.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,kBAAkB,EACxE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,CAAC,GAAG,SAAS,CAUf;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,SAAS,kBAAkB,EACvE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,CAAC,GAAG,SAAS,CAEf;AAED;gEACgE;AAChE,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,kBAAkB,EACtE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,CAAC,GAAG,SAAS,CAEf;AAED;;;;GAIG;AACH,wBAAgB,wCAAwC,CAAC,CAAC,SAAS,kBAAkB,EACnF,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,SAAS,CAAC,EAAE,EAC7B,SAAS,EAAE,SAAS,CAAC,EAAE,GACtB,CAAC,GAAG,SAAS,CAIf;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,kBAAkB,EACtE,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,CAAC,EACd,eAAe,EAAE,SAAS,CAAC,EAAE,WAG9B;AAED,wFAAwF;AACxF,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,kBAAkB,EACzB,cAAc,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;EAyBxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@larkup/workspace-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src",
|
|
@@ -324,8 +324,8 @@
|
|
|
324
324
|
"zod": "^4.4.3",
|
|
325
325
|
"mammoth": "^1.12.0",
|
|
326
326
|
"@larkup/marketplace": "0.3.10",
|
|
327
|
-
"@larkup/sandbox": "0.1.8",
|
|
328
327
|
"@larkup/scraper": "0.2.1",
|
|
328
|
+
"@larkup/sandbox": "0.1.8",
|
|
329
329
|
"@larkup/vector-stores": "0.1.27"
|
|
330
330
|
},
|
|
331
331
|
"devDependencies": {
|
|
@@ -99,7 +99,10 @@ import {
|
|
|
99
99
|
import { assistantSourceScopeFingerprint } from '../../../lib/chat/assistant-source-scope';
|
|
100
100
|
import { normalizeIncomingMessages } from '../../../lib/chat/message-input';
|
|
101
101
|
import { repairChatToolCall } from '../../../lib/chat/tool-call-repair';
|
|
102
|
-
import {
|
|
102
|
+
import {
|
|
103
|
+
explicitMediaEvidenceAssetId,
|
|
104
|
+
hasRetrievedSourceEvidence,
|
|
105
|
+
} from '../../../lib/chat/media-retrieval-routing';
|
|
103
106
|
import {
|
|
104
107
|
authorizeEnterpriseAiRequest,
|
|
105
108
|
trackEnterpriseAiUsage,
|
|
@@ -1458,6 +1461,26 @@ ${fieldLines}`;
|
|
|
1458
1461
|
output: preloadedEvidence,
|
|
1459
1462
|
});
|
|
1460
1463
|
|
|
1464
|
+
// End no-evidence turns deterministically. A prose model may answer
|
|
1465
|
+
// from general knowledge or mistake a sole media source for evidence
|
|
1466
|
+
// even when the retrieval instruction says not to.
|
|
1467
|
+
if (!hasRetrievedSourceEvidence(preloadedEvidence)) {
|
|
1468
|
+
const retrievalError =
|
|
1469
|
+
preloadedEvidence && typeof preloadedEvidence === 'object'
|
|
1470
|
+
? (preloadedEvidence as { error?: unknown }).error
|
|
1471
|
+
: undefined;
|
|
1472
|
+
const answer =
|
|
1473
|
+
typeof retrievalError === 'string' && retrievalError.trim()
|
|
1474
|
+
? retrievalError
|
|
1475
|
+
: "I couldn't find an answer to that in this project's data.";
|
|
1476
|
+
const answerId = `answer-${crypto.randomUUID()}`;
|
|
1477
|
+
writer.write({ type: 'text-start', id: answerId });
|
|
1478
|
+
writer.write({ type: 'text-delta', id: answerId, delta: answer });
|
|
1479
|
+
writer.write({ type: 'text-end', id: answerId });
|
|
1480
|
+
await mcp.close();
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1461
1484
|
// A PDF hit is a document-level locator, not necessarily the exact
|
|
1462
1485
|
// page. Read its bounded local page evidence before asking the chat
|
|
1463
1486
|
// model to compose an answer. This works whether or not visual
|
|
@@ -88,6 +88,7 @@ import {
|
|
|
88
88
|
clearlyTitleMatchedMediaAsset,
|
|
89
89
|
clearlyUnavailableTitleMatchedMediaAsset,
|
|
90
90
|
explicitlySelectedMediaAsset,
|
|
91
|
+
retrievalFallbackMediaAsset,
|
|
91
92
|
shouldKeepActiveMediaSource,
|
|
92
93
|
} from '../../../lib/chat/media-source-routing';
|
|
93
94
|
import { createTabularVisualization } from '../../../lib/chat/tabular-visualization';
|
|
@@ -348,24 +349,11 @@ function uniqueCompletedMediaFallback(
|
|
|
348
349
|
error: `The named media source "${unavailableTitleMatch.fileName}" is not available to Assistant chat. Enable its data group under Data → Groups, then ask again.`,
|
|
349
350
|
};
|
|
350
351
|
}
|
|
351
|
-
// A retrieval miss must not strand a single, unambiguous active media
|
|
352
|
-
// source. With several sources the host deliberately stays neutral and
|
|
353
|
-
// lets ordinary retrieval disambiguate rather than guessing the asset.
|
|
354
|
-
if (assets.length === 1) {
|
|
355
|
-
return {
|
|
356
|
-
query,
|
|
357
|
-
hits: [],
|
|
358
|
-
videoEvidence: {
|
|
359
|
-
mediaAssetId: assets[0].id,
|
|
360
|
-
retrievalFallback: 'single-active-media-source',
|
|
361
|
-
},
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
352
|
// A vector index can be temporarily unavailable while a completed video
|
|
365
353
|
// remains perfectly usable through its evidence store. Recover an asset
|
|
366
|
-
// only when its user-visible title has a clear lexical lead
|
|
367
|
-
//
|
|
368
|
-
const titleMatch =
|
|
354
|
+
// only when its user-visible title has a clear lexical lead. The mere fact
|
|
355
|
+
// that a project contains one video is not evidence for an unrelated query.
|
|
356
|
+
const titleMatch = retrievalFallbackMediaAsset(query, assets);
|
|
369
357
|
if (!titleMatch) return { query, hits: [] };
|
|
370
358
|
return {
|
|
371
359
|
query,
|
|
@@ -35,3 +35,13 @@ export function explicitMediaEvidenceAssetId(value: unknown): string | null {
|
|
|
35
35
|
}
|
|
36
36
|
return explicitMediaEvidenceAssetId(record.videoEvidence);
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
/** A deterministic gate before an answer model is allowed to compose prose. */
|
|
40
|
+
export function hasRetrievedSourceEvidence(value: unknown): boolean {
|
|
41
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
42
|
+
const record = value as { hits?: unknown };
|
|
43
|
+
return (
|
|
44
|
+
(Array.isArray(record.hits) && record.hits.length > 0) ||
|
|
45
|
+
Boolean(explicitMediaEvidenceAssetId(value))
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -38,6 +38,15 @@ export function explicitlySelectedMediaAsset<T extends RoutableMediaAsset>(
|
|
|
38
38
|
return clearlyTitleMatchedMediaAsset(query, assets);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** Recover media after a miss only when the user named the source clearly.
|
|
42
|
+
* A sole video is not evidence for every unrelated question. */
|
|
43
|
+
export function retrievalFallbackMediaAsset<T extends RoutableMediaAsset>(
|
|
44
|
+
query: string,
|
|
45
|
+
assets: readonly T[],
|
|
46
|
+
): T | undefined {
|
|
47
|
+
return clearlyTitleMatchedMediaAsset(query, assets);
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
/**
|
|
42
51
|
* Detect an explicitly named source that exists but is outside the Assistant
|
|
43
52
|
* source scope. A generic single-source fallback must not silently replace it
|