@corva/chat-core 0.0.1

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 ADDED
@@ -0,0 +1,51 @@
1
+ # @corva/chat-core
2
+
3
+ Platform-agnostic core of Corva Team Chat, shared by
4
+ [corva-web-frontend](https://github.com/corva-ai/corva-web-frontend) and
5
+ [corva-react-native-app](https://github.com/corva-ai/corva-react-native-app).
6
+
7
+ It holds everything that is not UI: the Revolt/Stoat API and socket client, chat stores, and the
8
+ `$$CORVA::` message wire format. Each app renders its own UI on top of it.
9
+
10
+ ## Rules
11
+
12
+ - **No platform globals.** The type environment is `es2022` only, with no DOM or Node types. The only
13
+ globals allowed are the timers and `console` declared in `src/platform.d.ts`. `fetch`, `WebSocket`,
14
+ storage, notifications and app-state events are injected by the host app through adapters.
15
+ - **No React.** Stores use `zustand/vanilla`; each app wraps them in its own hooks.
16
+ - **No UI dependencies** (`@corva/ui`, MUI, React Native).
17
+
18
+ Lint and typecheck enforce these rules.
19
+
20
+ ## Development
21
+
22
+ ```sh
23
+ nvm use
24
+ yarn install
25
+ yarn test # vitest, node environment
26
+ yarn lint # eslint + prettier
27
+ yarn typecheck
28
+ yarn build # tsup → dist/ (ESM + .d.ts)
29
+ ```
30
+
31
+ ### Trying a local build in an app
32
+
33
+ ```sh
34
+ yarn build && npx yalc publish # in this repo
35
+ npx yalc add @corva/chat-core # in the consuming app
36
+ ```
37
+
38
+ ## Publishing
39
+
40
+ ```sh
41
+ npm version patch # or minor / major
42
+ npm publish # prepublishOnly runs lint, typecheck, tests, build and package checks
43
+ git push --follow-tags
44
+ ```
45
+
46
+ Canary build for testing a branch in an app:
47
+
48
+ ```sh
49
+ npm version 0.0.0-$(git rev-parse --short HEAD) --no-git-tag-version
50
+ npm publish --tag canary && git checkout package.json
51
+ ```
@@ -0,0 +1,109 @@
1
+ declare const CORVA_SYS_PREFIX = "$$CORVA::";
2
+ declare const CORVA_MESSAGE_TYPES: {
3
+ readonly ALERT: "alert";
4
+ readonly FEED: "feed";
5
+ readonly ASK_CORVA: "ask";
6
+ readonly FORWARD: "fwd";
7
+ readonly APP_COMMENT: "cmt";
8
+ };
9
+ interface ForwardWirePayload {
10
+ cid: string;
11
+ mid: string;
12
+ cn: string;
13
+ priv: boolean;
14
+ n?: string;
15
+ ts?: string;
16
+ }
17
+ type CorvaSystemMessage = {
18
+ t: typeof CORVA_MESSAGE_TYPES.ALERT;
19
+ v: number;
20
+ d: AlertWirePayload;
21
+ } | {
22
+ t: typeof CORVA_MESSAGE_TYPES.FEED;
23
+ v: number;
24
+ d: FeedWirePayload;
25
+ } | {
26
+ t: typeof CORVA_MESSAGE_TYPES.ASK_CORVA;
27
+ v: number;
28
+ d: AskCorvaWirePayload;
29
+ } | {
30
+ t: typeof CORVA_MESSAGE_TYPES.FORWARD;
31
+ v: number;
32
+ d: ForwardWirePayload;
33
+ } | {
34
+ t: typeof CORVA_MESSAGE_TYPES.APP_COMMENT;
35
+ v: number;
36
+ d: AppCommentWirePayload;
37
+ };
38
+ type WireSeverity = 'c' | 'w' | 'i';
39
+ interface AlertWirePayload {
40
+ id: string;
41
+ defId?: string;
42
+ sev: WireSeverity;
43
+ ttl: string;
44
+ dsc: string;
45
+ trunc?: boolean;
46
+ app?: string;
47
+ assetId?: string;
48
+ assetName?: string;
49
+ }
50
+ interface FeedWirePayload {
51
+ id: string;
52
+ ft: string;
53
+ ttl: string;
54
+ dsc?: string;
55
+ assetId?: string;
56
+ usr?: string;
57
+ }
58
+ interface AskCorvaWirePayload {
59
+ id: string;
60
+ a: string;
61
+ aRef?: string;
62
+ cId?: number;
63
+ trunc?: boolean;
64
+ assetId?: number;
65
+ agentName?: string;
66
+ }
67
+ /**
68
+ * One attachment on the wire. Keys are single letters like every other field in these payloads:
69
+ * they ride inside the message body, which is truncated at MAX_COMMENT_BODY_LENGTH.
70
+ */
71
+ interface AttachmentWirePayload {
72
+ /** Attachment URL. */
73
+ u: string;
74
+ /** Original file name, with extension — lets the reader tell media apart from documents. */
75
+ n?: string;
76
+ /** File size in bytes. */
77
+ s?: number;
78
+ }
79
+ interface AppCommentWirePayload {
80
+ body: string;
81
+ app?: string;
82
+ usrId?: number;
83
+ autId?: number;
84
+ at?: string;
85
+ att?: string;
86
+ atts?: AttachmentWirePayload[];
87
+ actId?: string;
88
+ appId?: string;
89
+ dashId?: string;
90
+ appUrl?: string;
91
+ meta?: {
92
+ hd?: number;
93
+ bd?: number;
94
+ cd?: number;
95
+ };
96
+ snpId?: string;
97
+ trunc?: boolean;
98
+ }
99
+
100
+ /**
101
+ * Builds the wire-format content string for an AskCorva response.
102
+ */
103
+ declare function buildAskCorvaMessageContent(requestId: string, answer: string, answerRef?: string, isTruncated?: boolean, assetId?: number, agentName?: string, companyId?: number): string;
104
+ /**
105
+ * Builds the wire-format content string for a forwarded message.
106
+ */
107
+ declare function buildForwardMessageContent(sourceChannelId: string, messageId: string, channelName: string, isPrivate: boolean, note?: string, ts?: string): string;
108
+
109
+ export { type AlertWirePayload, type AppCommentWirePayload, type AskCorvaWirePayload, type AttachmentWirePayload, CORVA_MESSAGE_TYPES, CORVA_SYS_PREFIX, type CorvaSystemMessage, type FeedWirePayload, type ForwardWirePayload, type WireSeverity, buildAskCorvaMessageContent, buildForwardMessageContent };
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ // src/wire/corvaSystemMessage.ts
2
+ var CORVA_SYS_PREFIX = "$$CORVA::";
3
+ var CORVA_MESSAGE_TYPES = {
4
+ ALERT: "alert",
5
+ FEED: "feed",
6
+ ASK_CORVA: "ask",
7
+ FORWARD: "fwd",
8
+ APP_COMMENT: "cmt"
9
+ };
10
+
11
+ // src/wire/buildMessageContent.ts
12
+ function buildAskCorvaMessageContent(requestId, answer, answerRef, isTruncated, assetId, agentName, companyId) {
13
+ const payload = {
14
+ id: requestId,
15
+ a: answerRef ? "" : answer,
16
+ ...answerRef && { aRef: answerRef },
17
+ ...answerRef && companyId && { cId: companyId },
18
+ ...isTruncated && { trunc: true },
19
+ ...assetId && { assetId },
20
+ ...agentName && { agentName }
21
+ };
22
+ return `${CORVA_SYS_PREFIX}${JSON.stringify({ t: CORVA_MESSAGE_TYPES.ASK_CORVA, v: 1, d: payload })}`;
23
+ }
24
+ function buildForwardMessageContent(sourceChannelId, messageId, channelName, isPrivate, note, ts) {
25
+ const payload = {
26
+ cid: sourceChannelId,
27
+ mid: messageId,
28
+ cn: channelName,
29
+ priv: isPrivate,
30
+ ...note?.trim() && { n: note.trim() },
31
+ ...ts && { ts }
32
+ };
33
+ return `${CORVA_SYS_PREFIX}${JSON.stringify({ t: CORVA_MESSAGE_TYPES.FORWARD, v: 1, d: payload })}`;
34
+ }
35
+
36
+ export { CORVA_MESSAGE_TYPES, CORVA_SYS_PREFIX, buildAskCorvaMessageContent, buildForwardMessageContent };
37
+ //# sourceMappingURL=index.js.map
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wire/corvaSystemMessage.ts","../src/wire/buildMessageContent.ts"],"names":[],"mappings":";AAAO,IAAM,gBAAA,GAAmB;AAEzB,IAAM,mBAAA,GAAsB;AAAA,EACjC,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM,MAAA;AAAA,EACN,SAAA,EAAW,KAAA;AAAA,EACX,OAAA,EAAS,KAAA;AAAA,EACT,WAAA,EAAa;AACf;;;ACFO,SAAS,4BACd,SAAA,EACA,MAAA,EACA,WACA,WAAA,EACA,OAAA,EACA,WACA,SAAA,EACQ;AACR,EAAA,MAAM,OAAA,GAA+B;AAAA,IACnC,EAAA,EAAI,SAAA;AAAA,IACJ,CAAA,EAAG,YAAY,EAAA,GAAK,MAAA;AAAA,IACpB,GAAI,SAAA,IAAa,EAAE,IAAA,EAAM,SAAA,EAAU;AAAA,IACnC,GAAI,SAAA,IAAa,SAAA,IAAa,EAAE,KAAK,SAAA,EAAU;AAAA,IAC/C,GAAI,WAAA,IAAe,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,IACjC,GAAI,OAAA,IAAW,EAAE,OAAA,EAAQ;AAAA,IACzB,GAAI,SAAA,IAAa,EAAE,SAAA;AAAU,GAC/B;AACA,EAAA,OAAO,CAAA,EAAG,gBAAgB,CAAA,EAAG,IAAA,CAAK,UAAU,EAAE,CAAA,EAAG,mBAAA,CAAoB,SAAA,EAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,OAAA,EAAS,CAAC,CAAA,CAAA;AACrG;AAKO,SAAS,2BACd,eAAA,EACA,SAAA,EACA,WAAA,EACA,SAAA,EACA,MACA,EAAA,EACQ;AACR,EAAA,MAAM,OAAA,GAA8B;AAAA,IAClC,GAAA,EAAK,eAAA;AAAA,IACL,GAAA,EAAK,SAAA;AAAA,IACL,EAAA,EAAI,WAAA;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,GAAI,MAAM,IAAA,EAAK,IAAK,EAAE,CAAA,EAAG,IAAA,CAAK,MAAK,EAAE;AAAA,IACrC,GAAI,EAAA,IAAM,EAAE,EAAA;AAAG,GACjB;AACA,EAAA,OAAO,CAAA,EAAG,gBAAgB,CAAA,EAAG,IAAA,CAAK,UAAU,EAAE,CAAA,EAAG,mBAAA,CAAoB,OAAA,EAAS,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,OAAA,EAAS,CAAC,CAAA,CAAA;AACnG","file":"index.js","sourcesContent":["export const CORVA_SYS_PREFIX = '$$CORVA::';\n\nexport const CORVA_MESSAGE_TYPES = {\n ALERT: 'alert',\n FEED: 'feed',\n ASK_CORVA: 'ask',\n FORWARD: 'fwd',\n APP_COMMENT: 'cmt',\n} as const;\n\nexport interface ForwardWirePayload {\n cid: string;\n mid: string;\n cn: string;\n priv: boolean;\n n?: string;\n ts?: string; // ISO timestamp of the original message\n}\n\nexport type CorvaSystemMessage =\n | { t: typeof CORVA_MESSAGE_TYPES.ALERT; v: number; d: AlertWirePayload }\n | { t: typeof CORVA_MESSAGE_TYPES.FEED; v: number; d: FeedWirePayload }\n | { t: typeof CORVA_MESSAGE_TYPES.ASK_CORVA; v: number; d: AskCorvaWirePayload }\n | { t: typeof CORVA_MESSAGE_TYPES.FORWARD; v: number; d: ForwardWirePayload }\n | { t: typeof CORVA_MESSAGE_TYPES.APP_COMMENT; v: number; d: AppCommentWirePayload };\n\nexport type WireSeverity = 'c' | 'w' | 'i';\n\nexport interface AlertWirePayload {\n id: string;\n defId?: string;\n sev: WireSeverity;\n ttl: string;\n dsc: string;\n trunc?: boolean;\n app?: string;\n assetId?: string;\n assetName?: string;\n}\n\nexport interface FeedWirePayload {\n id: string;\n ft: string;\n ttl: string;\n dsc?: string;\n assetId?: string;\n usr?: string;\n}\n\nexport interface AskCorvaWirePayload {\n id: string;\n a: string;\n aRef?: string; // conversationId — fetch full answer from AskCorva backend when `a` is empty\n cId?: number; // sharer's company_id — askcorva.history records live under it, not the viewer's\n trunc?: boolean;\n assetId?: number;\n agentName?: string; // human-readable agent display name\n}\n\n/**\n * One attachment on the wire. Keys are single letters like every other field in these payloads:\n * they ride inside the message body, which is truncated at MAX_COMMENT_BODY_LENGTH.\n */\nexport interface AttachmentWirePayload {\n /** Attachment URL. */\n u: string;\n /** Original file name, with extension — lets the reader tell media apart from documents. */\n n?: string;\n /** File size in bytes. */\n s?: number;\n}\n\nexport interface AppCommentWirePayload {\n body: string;\n app?: string; // app display name\n usrId?: number; // forwarder corva user ID\n autId?: number; // comment author corva user ID\n at?: string; // activity type (e.g. \"dvd_comment\")\n att?: string; // first attachment URL — kept so pre-multi-attachment clients still render one file\n atts?: AttachmentWirePayload[];\n actId?: string; // activity ID for lazy-fetching full content\n appId?: string; // app definition ID for icon/info fetching\n dashId?: string; // dashboard ID for deep linking\n appUrl?: string; // full app URL with asset context\n meta?: { hd?: number; bd?: number; cd?: number }; // raw depth values in ft for viewer-side unit conversion\n snpId?: string; // settings snapshot ID — replaces dashboard-based settings fetching\n trunc?: boolean; // body was truncated, fetch full content from activity API\n}\n","import type { AskCorvaWirePayload, ForwardWirePayload } from './corvaSystemMessage';\nimport { CORVA_SYS_PREFIX, CORVA_MESSAGE_TYPES } from './corvaSystemMessage';\n\n/**\n * Builds the wire-format content string for an AskCorva response.\n */\nexport function buildAskCorvaMessageContent(\n requestId: string,\n answer: string,\n answerRef?: string,\n isTruncated?: boolean,\n assetId?: number,\n agentName?: string,\n companyId?: number\n): string {\n const payload: AskCorvaWirePayload = {\n id: requestId,\n a: answerRef ? '' : answer,\n ...(answerRef && { aRef: answerRef }),\n ...(answerRef && companyId && { cId: companyId }),\n ...(isTruncated && { trunc: true }),\n ...(assetId && { assetId }),\n ...(agentName && { agentName }),\n };\n return `${CORVA_SYS_PREFIX}${JSON.stringify({ t: CORVA_MESSAGE_TYPES.ASK_CORVA, v: 1, d: payload })}`;\n}\n\n/**\n * Builds the wire-format content string for a forwarded message.\n */\nexport function buildForwardMessageContent(\n sourceChannelId: string,\n messageId: string,\n channelName: string,\n isPrivate: boolean,\n note?: string,\n ts?: string\n): string {\n const payload: ForwardWirePayload = {\n cid: sourceChannelId,\n mid: messageId,\n cn: channelName,\n priv: isPrivate,\n ...(note?.trim() && { n: note.trim() }),\n ...(ts && { ts }),\n };\n return `${CORVA_SYS_PREFIX}${JSON.stringify({ t: CORVA_MESSAGE_TYPES.FORWARD, v: 1, d: payload })}`;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@corva/chat-core",
3
+ "version": "0.0.1",
4
+ "description": "Platform-agnostic core of Corva Team Chat, shared by the web and mobile apps",
5
+ "license": "UNLICENSED",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/corva-ai/corva-chat-core.git"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": false,
12
+ "main": "./dist/index.js",
13
+ "module": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ "./package.json": "./package.json",
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "default": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "engines": {
27
+ "node": "^24"
28
+ },
29
+ "packageManager": "yarn@1.22.22",
30
+ "scripts": {
31
+ "build": "tsup",
32
+ "test": "vitest run",
33
+ "test:watch": "vitest",
34
+ "typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.test.json",
35
+ "lint": "eslint . && prettier --check .",
36
+ "format": "prettier --write .",
37
+ "check-package": "publint --strict --pack npm && attw --pack . --profile esm-only",
38
+ "prepublishOnly": "yarn lint && yarn typecheck && yarn test && yarn build && yarn check-package"
39
+ },
40
+ "devDependencies": {
41
+ "@arethetypeswrong/cli": "0.18.5",
42
+ "@eslint/js": "10.0.1",
43
+ "@types/node": "24.13.6",
44
+ "eslint": "10.11.0",
45
+ "prettier": "3.9.9",
46
+ "publint": "0.3.24",
47
+ "tsup": "8.5.1",
48
+ "typescript": "5.9.3",
49
+ "typescript-eslint": "8.70.1",
50
+ "vite": "8.3.1",
51
+ "vitest": "5.0.1"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }