@prur/dsh-chat-service 0.1.14

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.
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Hand-written TYPERT host manifest for the chat Remote namespace. The
3
+ * official typert generator emits this artifact from the service face during
4
+ * the harness repository build; this package hand-writes the same contract
5
+ * (wire schemas + invocation descriptors) because the bridge repo builds
6
+ * packages with plain tsc. The typert-loader validates every field at mount
7
+ * time; the isolated-instance matrix asserts acceptance on boot.
8
+ * @module @prur/dsh-chat-service/typert
9
+ */
10
+ import { z } from 'zod';
11
+ const conversationIdSchema = z.string().regex(/^[A-Za-z0-9_-]{1,64}$/);
12
+ const optionalStringSchema = z.string().min(1).optional();
13
+ const optionalNumberSchema = z.number().int().nonnegative().optional();
14
+ const optionalPositiveIntSchema = z.number().int().positive().optional();
15
+ const textBlockSchema = z.object({
16
+ type: z.literal('text'),
17
+ text: z.string(),
18
+ }).readonly();
19
+ const messageSchema = z.object({
20
+ seq: z.number().int().nonnegative(),
21
+ role: z.enum(['user', 'assistant', 'system']),
22
+ blocks: z.array(textBlockSchema).readonly(),
23
+ model: z.string().optional(),
24
+ provider: z.string().optional(),
25
+ createdAt: z.number().int().nonnegative().optional(),
26
+ error: z.string().optional(),
27
+ }).readonly();
28
+ const summarySchema = z.object({
29
+ conversationId: conversationIdSchema,
30
+ title: z.string().nullable(),
31
+ provider: z.string(),
32
+ model: z.string(),
33
+ updatedAt: z.number().int().nonnegative(),
34
+ messageCount: z.number().int().nonnegative(),
35
+ running: z.boolean(),
36
+ }).readonly();
37
+ const settingsSchema = z.object({
38
+ conversationId: conversationIdSchema,
39
+ title: z.string().nullable(),
40
+ provider: z.string(),
41
+ model: z.string(),
42
+ temperature: z.number().nullable(),
43
+ contextMessages: z.number().int().positive().nullable(),
44
+ systemPrompt: z.string().nullable(),
45
+ updatedAt: z.number().int().nonnegative(),
46
+ }).readonly();
47
+ const patchSchema = z.object({
48
+ systemPrompt: z.string().nullable().optional(),
49
+ temperature: z.number().nullable().optional(),
50
+ contextMessages: z.number().int().positive().nullable().optional(),
51
+ }).readonly();
52
+ const contentSchema = z.array(textBlockSchema).min(1).readonly();
53
+ const emptyOkSchema = z.object({}).readonly();
54
+ const listResultSchema = z.object({
55
+ ok: z.literal(true),
56
+ value: z.object({ items: z.array(summarySchema).readonly() }),
57
+ }).readonly();
58
+ const createResultSchema = z.object({
59
+ ok: z.literal(true),
60
+ value: z.object({ conversationId: conversationIdSchema }),
61
+ }).readonly();
62
+ const emptyResultSchema = z.object({
63
+ ok: z.literal(true),
64
+ value: emptyOkSchema,
65
+ }).readonly();
66
+ const historyResultSchema = z.object({
67
+ ok: z.literal(true),
68
+ value: z.object({
69
+ items: z.array(messageSchema).readonly(),
70
+ hasMore: z.boolean(),
71
+ }),
72
+ }).readonly();
73
+ const sendResultSchema = z.object({
74
+ ok: z.literal(true),
75
+ value: z.object({ accepted: z.literal(true) }),
76
+ }).readonly();
77
+ const selectModelResultSchema = z.object({
78
+ ok: z.literal(true),
79
+ value: z.object({ provider: z.string(), model: z.string() }),
80
+ }).readonly();
81
+ const updateResultSchema = z.object({
82
+ ok: z.literal(true),
83
+ value: settingsSchema,
84
+ }).readonly();
85
+ const RESULT_TYPE_SYMBOLS = {
86
+ list: '@prur/dsh-chat-service/types#ChatListResult',
87
+ create: '@prur/dsh-chat-service/types#ChatCreateResult',
88
+ rename: '@prur/dsh-chat-service/types#ChatEmptyResult',
89
+ delete: '@prur/dsh-chat-service/types#ChatEmptyResult',
90
+ history: '@prur/dsh-chat-service/types#ChatHistoryResult',
91
+ send: '@prur/dsh-chat-service/types#ChatSendResult',
92
+ cancel: '@prur/dsh-chat-service/types#ChatEmptyResult',
93
+ selectModel: '@prur/dsh-chat-service/types#ChatSelectModelResult',
94
+ update: '@prur/dsh-chat-service/types#ChatUpdateResult',
95
+ };
96
+ const invocation = (id, method, parameters, result) => ({
97
+ id: `@prur/dsh-chat-service#${id}`,
98
+ service: 'chat',
99
+ namespace: 'chat',
100
+ method,
101
+ invocation: { kind: 'direct' },
102
+ parameters,
103
+ result: {
104
+ mode: 'strict',
105
+ typeSymbol: RESULT_TYPE_SYMBOLS[method],
106
+ schema: result,
107
+ },
108
+ });
109
+ export const TYPERT = {
110
+ package: '@prur/dsh-chat-service',
111
+ face: 'host',
112
+ schemas: [],
113
+ invocations: [
114
+ invocation('chat/list', 'list', [], listResultSchema),
115
+ invocation('chat/create', 'create', [
116
+ { name: 'provider', wire: 'provider', source: 'json', acceptsUndefined: true, codec: { mode: 'strict', typeSymbol: 'string', schema: optionalStringSchema } },
117
+ { name: 'model', wire: 'model', source: 'json', acceptsUndefined: true, codec: { mode: 'strict', typeSymbol: 'string', schema: optionalStringSchema } },
118
+ { name: 'title', wire: 'title', source: 'json', acceptsUndefined: true, codec: { mode: 'strict', typeSymbol: 'string', schema: optionalStringSchema } },
119
+ ], createResultSchema),
120
+ invocation('chat/rename', 'rename', [
121
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
122
+ { name: 'title', wire: 'title', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: z.string().min(1) } },
123
+ ], emptyResultSchema),
124
+ invocation('chat/delete', 'delete', [
125
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
126
+ ], emptyResultSchema),
127
+ invocation('chat/history', 'history', [
128
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
129
+ { name: 'beforeSeq', wire: 'beforeSeq', source: 'json', acceptsUndefined: true, codec: { mode: 'strict', typeSymbol: 'number', schema: optionalNumberSchema } },
130
+ { name: 'maxMessages', wire: 'maxMessages', source: 'json', acceptsUndefined: true, codec: { mode: 'strict', typeSymbol: 'number', schema: optionalPositiveIntSchema } },
131
+ ], historyResultSchema),
132
+ invocation('chat/send', 'send', [
133
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
134
+ { name: 'content', wire: 'content', source: 'json', codec: { mode: 'strict', typeSymbol: '@prur/dsh-chat-service/types#ChatTextBlock[]', schema: contentSchema } },
135
+ ], sendResultSchema),
136
+ invocation('chat/cancel', 'cancel', [
137
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
138
+ ], emptyResultSchema),
139
+ invocation('chat/selectModel', 'selectModel', [
140
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
141
+ { name: 'provider', wire: 'provider', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: z.string().min(1) } },
142
+ { name: 'model', wire: 'model', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: z.string().min(1) } },
143
+ ], selectModelResultSchema),
144
+ invocation('chat/update', 'update', [
145
+ { name: 'conversationId', wire: 'conversationId', source: 'json', codec: { mode: 'strict', typeSymbol: 'string', schema: conversationIdSchema } },
146
+ { name: 'patch', wire: 'patch', source: 'json', codec: { mode: 'strict', typeSymbol: '@prur/dsh-chat-service/types#ChatUpdatePatch', schema: patchSchema } },
147
+ ], updateResultSchema),
148
+ ],
149
+ model: {
150
+ services: [],
151
+ events: [],
152
+ objects: [],
153
+ },
154
+ };
155
+ export default TYPERT;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Client projection of the chat Remote namespace, mirroring the
3
+ * `typert.remote-client` artifact the official generator emits. Inert while
4
+ * the package declares no client half (`dsh: null`); kept for contract
5
+ * completeness and future client tooling.
6
+ * @module @prur/dsh-chat-service/remote
7
+ */
8
+ /** One remote-client invocation descriptor (mirror of the host face). */
9
+ interface RemoteInvocationEntry {
10
+ readonly id: string;
11
+ readonly service: string;
12
+ readonly namespace: string;
13
+ readonly method: string;
14
+ readonly invocation: {
15
+ readonly kind: 'direct';
16
+ };
17
+ readonly parameters: readonly {
18
+ readonly name: string;
19
+ readonly wire: string;
20
+ readonly source: 'json';
21
+ readonly acceptsUndefined?: true;
22
+ }[];
23
+ readonly result: {
24
+ readonly mode: 'strict';
25
+ readonly typeSymbol: string;
26
+ };
27
+ }
28
+ export declare const TYPERT_REMOTE: {
29
+ package: string;
30
+ descriptors: RemoteInvocationEntry[];
31
+ };
32
+ export default TYPERT_REMOTE;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Client projection of the chat Remote namespace, mirroring the
3
+ * `typert.remote-client` artifact the official generator emits. Inert while
4
+ * the package declares no client half (`dsh: null`); kept for contract
5
+ * completeness and future client tooling.
6
+ * @module @prur/dsh-chat-service/remote
7
+ */
8
+ const RESULT_TYPE_SYMBOLS = {
9
+ list: '@prur/dsh-chat-service/types#ChatListResult',
10
+ create: '@prur/dsh-chat-service/types#ChatCreateResult',
11
+ rename: '@prur/dsh-chat-service/types#ChatEmptyResult',
12
+ delete: '@prur/dsh-chat-service/types#ChatEmptyResult',
13
+ history: '@prur/dsh-chat-service/types#ChatHistoryResult',
14
+ send: '@prur/dsh-chat-service/types#ChatSendResult',
15
+ cancel: '@prur/dsh-chat-service/types#ChatEmptyResult',
16
+ selectModel: '@prur/dsh-chat-service/types#ChatSelectModelResult',
17
+ update: '@prur/dsh-chat-service/types#ChatUpdateResult',
18
+ };
19
+ const descriptor = (id, method, parameters) => ({
20
+ id: `@prur/dsh-chat-service#${id}`,
21
+ service: 'chat',
22
+ namespace: 'chat',
23
+ method,
24
+ invocation: { kind: 'direct' },
25
+ parameters,
26
+ result: {
27
+ mode: 'strict',
28
+ typeSymbol: RESULT_TYPE_SYMBOLS[method],
29
+ },
30
+ });
31
+ export const TYPERT_REMOTE = {
32
+ package: '@prur/dsh-chat-service',
33
+ descriptors: [
34
+ descriptor('chat/list', 'list', []),
35
+ descriptor('chat/create', 'create', [
36
+ { name: 'provider', wire: 'provider', source: 'json', acceptsUndefined: true },
37
+ { name: 'model', wire: 'model', source: 'json', acceptsUndefined: true },
38
+ { name: 'title', wire: 'title', source: 'json', acceptsUndefined: true },
39
+ ]),
40
+ descriptor('chat/rename', 'rename', [
41
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
42
+ { name: 'title', wire: 'title', source: 'json' },
43
+ ]),
44
+ descriptor('chat/delete', 'delete', [
45
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
46
+ ]),
47
+ descriptor('chat/history', 'history', [
48
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
49
+ { name: 'beforeSeq', wire: 'beforeSeq', source: 'json', acceptsUndefined: true },
50
+ { name: 'maxMessages', wire: 'maxMessages', source: 'json', acceptsUndefined: true },
51
+ ]),
52
+ descriptor('chat/send', 'send', [
53
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
54
+ { name: 'content', wire: 'content', source: 'json' },
55
+ ]),
56
+ descriptor('chat/cancel', 'cancel', [
57
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
58
+ ]),
59
+ descriptor('chat/selectModel', 'selectModel', [
60
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
61
+ { name: 'provider', wire: 'provider', source: 'json' },
62
+ { name: 'model', wire: 'model', source: 'json' },
63
+ ]),
64
+ descriptor('chat/update', 'update', [
65
+ { name: 'conversationId', wire: 'conversationId', source: 'json' },
66
+ { name: 'patch', wire: 'patch', source: 'json' },
67
+ ]),
68
+ ],
69
+ };
70
+ export default TYPERT_REMOTE;
package/lib/types.d.ts ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Wire types for the chat Typert Remote namespace: a plain model chat domain
3
+ * that never enters the session/agent loop. The host-side authoritative
4
+ * shape lives here; the DSH-Mobile SDK mirrors it in `ChatRemoteClient`.
5
+ * @module @prur/dsh-chat-service/src/types
6
+ */
7
+ /** One text content block (v1 keeps chat text-only; image blocks arrive with M3). */
8
+ export interface ChatTextBlock {
9
+ readonly type: 'text';
10
+ readonly text: string;
11
+ }
12
+ /** Reason a running turn settled, carried by the `chat/status` event. */
13
+ export type ChatTurnReason = 'completed' | 'aborted' | 'error' | 'max-tokens' | 'context-trimmed';
14
+ /**
15
+ * One chat message node. `seq` is the conversation's monotonic message
16
+ * sequence (identity and reconnect-convergence anchor — never reused).
17
+ */
18
+ export interface ChatMessage {
19
+ readonly seq: number;
20
+ readonly role: 'user' | 'assistant' | 'system';
21
+ readonly blocks: readonly ChatTextBlock[];
22
+ /** Provider route that produced an assistant message. */
23
+ readonly model?: string;
24
+ /** Provider route key that produced an assistant message. */
25
+ readonly provider?: string;
26
+ /** Unix epoch milliseconds when the message settled. */
27
+ readonly createdAt?: number;
28
+ /** Presentation string when an assistant turn failed. */
29
+ readonly error?: string;
30
+ }
31
+ /** Live run state of one conversation. */
32
+ export interface ChatStatus {
33
+ readonly running: boolean;
34
+ /** Identity of the settled-or-in-flight assistant turn (its message seq). */
35
+ readonly turn: number;
36
+ readonly reason?: ChatTurnReason;
37
+ }
38
+ /** One conversation row for `chat/list`. */
39
+ export interface ChatConversationSummary {
40
+ readonly conversationId: string;
41
+ readonly title: string | null;
42
+ readonly provider: string;
43
+ readonly model: string;
44
+ /** Unix epoch milliseconds of the last message or setting change. */
45
+ readonly updatedAt: number;
46
+ readonly messageCount: number;
47
+ readonly running: boolean;
48
+ }
49
+ /** Settings view of one conversation (returned by `chat/update`). */
50
+ export interface ChatConversationSettings {
51
+ readonly conversationId: string;
52
+ readonly title: string | null;
53
+ readonly provider: string;
54
+ readonly model: string;
55
+ readonly temperature: number | null;
56
+ readonly contextMessages: number | null;
57
+ readonly systemPrompt: string | null;
58
+ readonly updatedAt: number;
59
+ }
60
+ /** Successful chats of `chat/list`. */
61
+ export type ChatListResult = {
62
+ readonly ok: true;
63
+ readonly value: {
64
+ readonly items: readonly ChatConversationSummary[];
65
+ };
66
+ };
67
+ /** Successful value of `chat/create`. */
68
+ export type ChatCreateResult = {
69
+ readonly ok: true;
70
+ readonly value: {
71
+ readonly conversationId: string;
72
+ };
73
+ };
74
+ /** Successful value of `chat/rename` and `chat/delete`. */
75
+ export type ChatEmptyResult = {
76
+ readonly ok: true;
77
+ readonly value: Record<string, never>;
78
+ };
79
+ /** Successful value of `chat/history`. */
80
+ export type ChatHistoryResult = {
81
+ readonly ok: true;
82
+ readonly value: {
83
+ readonly items: readonly ChatMessage[];
84
+ readonly hasMore: boolean;
85
+ };
86
+ };
87
+ /** Successful value of `chat/send`. */
88
+ export type ChatSendResult = {
89
+ readonly ok: true;
90
+ readonly value: {
91
+ readonly accepted: true;
92
+ };
93
+ };
94
+ /** Successful value of `chat/selectModel`. */
95
+ export type ChatSelectModelResult = {
96
+ readonly ok: true;
97
+ readonly value: {
98
+ readonly provider: string;
99
+ readonly model: string;
100
+ };
101
+ };
102
+ /** Successful value of `chat/update`. */
103
+ export type ChatUpdateResult = {
104
+ readonly ok: true;
105
+ readonly value: ChatConversationSettings;
106
+ };
package/lib/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Wire types for the chat Typert Remote namespace: a plain model chat domain
3
+ * that never enters the session/agent loop. The host-side authoritative
4
+ * shape lives here; the DSH-Mobile SDK mirrors it in `ChatRemoteClient`.
5
+ * @module @prur/dsh-chat-service/src/types
6
+ */
7
+ export {};
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@prur/dsh-chat-service",
3
+ "version": "0.1.14",
4
+ "description": "Typert Remote namespace exposing a plain streaming model chat (no agent loop) to DSH Mobile clients",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/prur/dsh-mobile-host-bridge.git",
8
+ "directory": "packages/chat-service"
9
+ },
10
+ "type": "module",
11
+ "main": "lib/index.js",
12
+ "types": "lib/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./lib/index.d.ts",
16
+ "default": "./lib/index.js"
17
+ },
18
+ "./types": {
19
+ "types": "./lib/types.d.ts",
20
+ "default": "./lib/types.js"
21
+ },
22
+ "./typert": {
23
+ "types": "./lib/typert.host.d.ts",
24
+ "default": "./lib/typert.host.js"
25
+ },
26
+ "./remote": {
27
+ "types": "./lib/typert.remote-client.d.ts",
28
+ "default": "./lib/typert.remote-client.js"
29
+ },
30
+ "./src/*": "./src/*",
31
+ "./package.json": "./package.json"
32
+ },
33
+ "dsh": null,
34
+ "dependencies": {
35
+ "zod": "^4.4.3",
36
+ "@deepseek-ai/schemastery": "^3.18.1",
37
+ "ws": "^8.21.0",
38
+ "@prur/dsh-client-connection-mobile": "^0.1.14"
39
+ },
40
+ "peerDependencies": {
41
+ "@deepseek-ai/cordis": "^4.0.1",
42
+ "@deepseek-ai/dsh-invariants": "^0.1.0-rc.8 || ^0.1.1-rc.2",
43
+ "@deepseek-ai/dsh-llm": "^0.1.0-rc.8 || ^0.1.1-rc.2",
44
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.8 || ^0.1.1-rc.2",
45
+ "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.8 || ^0.1.1-rc.2"
46
+ },
47
+ "files": [
48
+ "lib/*.js",
49
+ "lib/*.d.ts"
50
+ ],
51
+ "license": "MIT",
52
+ "scripts": {
53
+ "build": "tsc -p tsconfig.json"
54
+ }
55
+ }