cngkit 1.1.23 → 1.1.25
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 -7
- package/dist/{chunk-AS7FIJWP.js → chunk-2Y5FMKFS.js} +3 -4
- package/dist/chunk-2Y5FMKFS.js.map +1 -0
- package/dist/{chunk-VMTXY4KQ.js → chunk-3VDQDFHG.js} +14 -6
- package/dist/chunk-3VDQDFHG.js.map +1 -0
- package/dist/{chunk-U725ZHCI.js → chunk-55IPOJ3R.js} +2 -2
- package/dist/{chunk-BXS4IKUA.js → chunk-DDQ5TITN.js} +91 -15
- package/dist/chunk-DDQ5TITN.js.map +1 -0
- package/dist/{chunk-BRFWVQI4.js → chunk-LC4CYVCT.js} +1 -1
- package/dist/chunk-LC4CYVCT.js.map +1 -0
- package/dist/{chunk-YALWTRIP.js → chunk-LNFZT3R3.js} +2 -2
- package/dist/{chunk-JNHW72SU.js → chunk-QCAHQE7Q.js} +14 -9
- package/dist/chunk-QCAHQE7Q.js.map +1 -0
- package/dist/{chunk-WIEYHKQA.js → chunk-TC6YIS5Z.js} +12 -15
- package/dist/chunk-TC6YIS5Z.js.map +1 -0
- package/dist/{chunk-67FUBMNB.js → chunk-X3UQB2CC.js} +2 -2
- package/dist/{chunk-67FUBMNB.js.map → chunk-X3UQB2CC.js.map} +1 -1
- package/dist/{chunk-GYRLVNJX.js → chunk-YIU6G2D3.js} +2 -2
- package/dist/{chunk-3BATDTKU.js → chunk-YPGDQ6P2.js} +2 -4
- package/dist/chunk-YPGDQ6P2.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/coderoom/index.js +3 -3
- package/dist/commands/coderoom/join.js +14 -5
- package/dist/commands/coderoom/join.js.map +1 -1
- package/dist/commands/coderoom/share.js +4 -4
- package/dist/commands/hookify/index.js +3 -3
- package/dist/commands/hookify/ingest.js +3 -3
- package/dist/commands/hooks/index.js +3 -3
- package/dist/commands/hooks/install.js +3 -3
- package/dist/commands/hooks/uninstall.js +3 -3
- package/dist/commands/index.js +3 -3
- package/dist/commands/knowledges/audiences.js +6 -6
- package/dist/commands/knowledges/cat.js +6 -6
- package/dist/commands/knowledges/files.js +6 -6
- package/dist/commands/knowledges/find.js +6 -6
- package/dist/commands/knowledges/find.js.map +1 -1
- package/dist/commands/knowledges/glob.js +5 -5
- package/dist/commands/knowledges/grep.js +5 -5
- package/dist/commands/knowledges/grep.js.map +1 -1
- package/dist/commands/knowledges/head.js +6 -6
- package/dist/commands/knowledges/index.js +3 -3
- package/dist/commands/knowledges/list.js +6 -6
- package/dist/commands/knowledges/ls.js +6 -6
- package/dist/commands/knowledges/ls.js.map +1 -1
- package/dist/commands/knowledges/read.js +5 -5
- package/dist/commands/knowledges/read.js.map +1 -1
- package/dist/commands/knowledges/realpath.js +3 -3
- package/dist/commands/knowledges/realpath.js.map +1 -1
- package/dist/commands/knowledges/search.js +6 -6
- package/dist/commands/knowledges/stat.js +6 -6
- package/dist/commands/knowledges/status.js +6 -6
- package/dist/commands/knowledges/tail.js +6 -6
- package/dist/commands/knowledges/tree.js +6 -6
- package/dist/commands/login.js +2 -2
- package/dist/commands/scrub.js +17 -14
- package/dist/commands/scrub.js.map +1 -1
- package/dist/commands/transcripts.js +37 -27
- package/dist/commands/transcripts.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-3BATDTKU.js.map +0 -1
- package/dist/chunk-AS7FIJWP.js.map +0 -1
- package/dist/chunk-BRFWVQI4.js.map +0 -1
- package/dist/chunk-BXS4IKUA.js.map +0 -1
- package/dist/chunk-JNHW72SU.js.map +0 -1
- package/dist/chunk-VMTXY4KQ.js.map +0 -1
- package/dist/chunk-WIEYHKQA.js.map +0 -1
- /package/dist/{chunk-U725ZHCI.js.map → chunk-55IPOJ3R.js.map} +0 -0
- /package/dist/{chunk-YALWTRIP.js.map → chunk-LNFZT3R3.js.map} +0 -0
- /package/dist/{chunk-GYRLVNJX.js.map → chunk-YIU6G2D3.js.map} +0 -0
package/README.md
CHANGED
|
@@ -72,8 +72,9 @@ The CLI currently has six main jobs:
|
|
|
72
72
|
## Coderoom
|
|
73
73
|
|
|
74
74
|
Coderoom is a live room for quickly sharing a working tree with another developer or agent.
|
|
75
|
-
One machine creates a server-owned room code
|
|
76
|
-
|
|
75
|
+
One machine creates a server-owned room code and prints a copy-ready partner command with
|
|
76
|
+
a guest acceptance token. The partner can join with that command without a separate approval
|
|
77
|
+
prompt; joins without the token still wait for host approval.
|
|
77
78
|
|
|
78
79
|
Start a room:
|
|
79
80
|
|
|
@@ -84,14 +85,15 @@ cngkit coderoom share
|
|
|
84
85
|
Join a room:
|
|
85
86
|
|
|
86
87
|
```bash
|
|
87
|
-
cngkit coderoom join <room-code>
|
|
88
|
+
cngkit coderoom join <room-code> --acceptance-token <token>
|
|
88
89
|
```
|
|
89
90
|
|
|
90
91
|
Coderoom deliberately skips `.git/` and files ignored by `.gitignore`. Room codes,
|
|
91
|
-
participants, join requests, and file IDs are created by the
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
guest acceptance tokens, participants, join requests, and file IDs are created by the
|
|
93
|
+
backend. The CLI prints every initial snapshot upload, live file upload, delete upload,
|
|
94
|
+
backend storage acknowledgement, and shutdown status. The room Durable Object stores the
|
|
95
|
+
file tree and hashes, keeps small file bodies directly, and uses R2 for large file bodies.
|
|
96
|
+
The current conflict rule is simple: the latest received change wins.
|
|
95
97
|
|
|
96
98
|
## Harness Knowledges
|
|
97
99
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/features/knowledges/knowledges-input.ts
|
|
2
|
-
var storedTopicsRoot = "
|
|
2
|
+
var storedTopicsRoot = "topics";
|
|
3
3
|
function normalizeAudienceId(value) {
|
|
4
4
|
if (value === void 0) {
|
|
5
5
|
return void 0;
|
|
@@ -26,7 +26,6 @@ function normalizeCatalogPath(value) {
|
|
|
26
26
|
if (relativePath === storedTopicsRoot || relativePath.startsWith(`${storedTopicsRoot}/`)) {
|
|
27
27
|
return relativePath;
|
|
28
28
|
}
|
|
29
|
-
const topicRelativePath = relativePath.startsWith("topics/") ? relativePath.slice("topics/".length) : relativePath;
|
|
30
29
|
const [firstSegment, ...restSegments] = relativePath.split("/");
|
|
31
30
|
if (!firstSegment) {
|
|
32
31
|
return relativePath;
|
|
@@ -44,7 +43,7 @@ function normalizeCatalogPath(value) {
|
|
|
44
43
|
case "tools":
|
|
45
44
|
return `${storedTopicsRoot}/${firstSegment}${restSegments.length > 0 ? `/${restSegments.join("/")}` : ""}`;
|
|
46
45
|
default:
|
|
47
|
-
return `${storedTopicsRoot}/${
|
|
46
|
+
return `${storedTopicsRoot}/${relativePath}`;
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
function normalizeFilesystemCatalogPath(value) {
|
|
@@ -85,4 +84,4 @@ export {
|
|
|
85
84
|
formatCatalogPathForDisplay,
|
|
86
85
|
normalizeGrepMode
|
|
87
86
|
};
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
87
|
+
//# sourceMappingURL=chunk-2Y5FMKFS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/knowledges/knowledges-input.ts"],"sourcesContent":["import type { CngApi } from \"@cng/client\";\n\nconst storedTopicsRoot = \"topics\";\n\nexport function normalizeAudienceId(\n value: string | undefined\n): CngApi.HarnessAudienceId | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n switch (value) {\n case \"all\":\n case \"operators\":\n case \"builders\":\n case \"researchers\":\n case \"agent-makers\":\n return value;\n default:\n throw new Error(\n `Unknown audience \"${value}\". Run cngkit knowledges audiences to see supported values.`\n );\n }\n}\n\nexport function normalizeCatalogPath(value: string): string {\n const trimmed = value.trim();\n if (trimmed === \"/\" || trimmed === \"\") {\n return storedTopicsRoot;\n }\n\n const relativePath = trimmed.replace(/^\\/+/, \"\");\n if (relativePath === storedTopicsRoot || relativePath.startsWith(`${storedTopicsRoot}/`)) {\n return relativePath;\n }\n\n const [firstSegment, ...restSegments] = relativePath.split(\"/\");\n if (!firstSegment) {\n return relativePath;\n }\n\n switch (firstSegment) {\n case \"concepts\":\n case \"domains\":\n case \"formats\":\n case \"languages\":\n case \"libraries\":\n case \"patterns\":\n case \"platforms\":\n case \"procedures\":\n case \"protocols\":\n case \"tools\":\n return `${storedTopicsRoot}/${firstSegment}${restSegments.length > 0 ? `/${restSegments.join(\"/\")}` : \"\"}`;\n default:\n return `${storedTopicsRoot}/${relativePath}`;\n }\n}\n\nexport function normalizeFilesystemCatalogPath(value: string): string {\n const trimmed = value.trim();\n if (trimmed === \"/\" || trimmed === \"\") {\n return storedTopicsRoot;\n }\n\n return normalizeCatalogPath(trimmed);\n}\n\nexport function formatCatalogPathForDisplay(value: string): string {\n const normalized = value.replace(/\\/+$/, \"\");\n if (normalized === storedTopicsRoot) {\n return \"/\";\n }\n\n if (normalized.startsWith(`${storedTopicsRoot}/`)) {\n return `/${normalized.slice(storedTopicsRoot.length + 1)}`;\n }\n\n return value;\n}\n\nexport function normalizeGrepMode(value: string | undefined): CngApi.HarnessGrepOutputMode {\n if (value === undefined) {\n return \"content\";\n }\n\n switch (value) {\n case \"content\":\n case \"files_with_matches\":\n case \"count\":\n return value;\n default:\n throw new Error(\"Unknown grep mode. Use one of: content, files_with_matches, count.\");\n }\n}\n"],"mappings":";AAEA,IAAM,mBAAmB;AAElB,SAAS,oBACd,OACsC;AACtC,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,UAAQ,OAAO;AAAA,IACb,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,YAAM,IAAI;AAAA,QACR,qBAAqB,KAAK;AAAA,MAC5B;AAAA,EACJ;AACF;AAEO,SAAS,qBAAqB,OAAuB;AAC1D,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,OAAO,YAAY,IAAI;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,QAAQ,QAAQ,QAAQ,EAAE;AAC/C,MAAI,iBAAiB,oBAAoB,aAAa,WAAW,GAAG,gBAAgB,GAAG,GAAG;AACxF,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,cAAc,GAAG,YAAY,IAAI,aAAa,MAAM,GAAG;AAC9D,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,UAAQ,cAAc;AAAA,IACpB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,GAAG,gBAAgB,IAAI,YAAY,GAAG,aAAa,SAAS,IAAI,IAAI,aAAa,KAAK,GAAG,CAAC,KAAK,EAAE;AAAA,IAC1G;AACE,aAAO,GAAG,gBAAgB,IAAI,YAAY;AAAA,EAC9C;AACF;AAEO,SAAS,+BAA+B,OAAuB;AACpE,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,OAAO,YAAY,IAAI;AACrC,WAAO;AAAA,EACT;AAEA,SAAO,qBAAqB,OAAO;AACrC;AAEO,SAAS,4BAA4B,OAAuB;AACjE,QAAM,aAAa,MAAM,QAAQ,QAAQ,EAAE;AAC3C,MAAI,eAAe,kBAAkB;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,WAAW,WAAW,GAAG,gBAAgB,GAAG,GAAG;AACjD,WAAO,IAAI,WAAW,MAAM,iBAAiB,SAAS,CAAC,CAAC;AAAA,EAC1D;AAEA,SAAO;AACT;AAEO,SAAS,kBAAkB,OAAyD;AACzF,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,UAAQ,OAAO;AAAA,IACb,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,YAAM,IAAI,MAAM,oEAAoE;AAAA,EACxF;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
formatCatalogPathForDisplay
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2Y5FMKFS.js";
|
|
4
4
|
import {
|
|
5
5
|
singleLine
|
|
6
6
|
} from "./chunk-XQGLUQFM.js";
|
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
// src/features/knowledges/knowledges-output.tsx
|
|
9
9
|
import { Box, Text } from "ink";
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
function KnowCatalogSummary({
|
|
11
|
+
function KnowCatalogSummary({
|
|
12
|
+
catalog
|
|
13
|
+
}) {
|
|
12
14
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
13
15
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
14
16
|
/* @__PURE__ */ jsx(Text, { bold: true, children: "Catalog: " }),
|
|
@@ -31,7 +33,9 @@ function KnowCatalogSummary({ catalog }) {
|
|
|
31
33
|
] })
|
|
32
34
|
] });
|
|
33
35
|
}
|
|
34
|
-
function KnowAudienceList({
|
|
36
|
+
function KnowAudienceList({
|
|
37
|
+
audiences
|
|
38
|
+
}) {
|
|
35
39
|
if (audiences.length === 0) {
|
|
36
40
|
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "No audiences available." });
|
|
37
41
|
}
|
|
@@ -71,7 +75,9 @@ function KnowSearchResults({
|
|
|
71
75
|
/* @__PURE__ */ jsx(Text, { children: singleLine(result.description || result.contentPreview) })
|
|
72
76
|
] }, result.id)) });
|
|
73
77
|
}
|
|
74
|
-
function KnowTopicList({
|
|
78
|
+
function KnowTopicList({
|
|
79
|
+
topics
|
|
80
|
+
}) {
|
|
75
81
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: topics.map((topic) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
76
82
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
77
83
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: topic.name }),
|
|
@@ -91,7 +97,9 @@ function KnowTopicList({ topics }) {
|
|
|
91
97
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: singleLine(topic.description) })
|
|
92
98
|
] }, topic.id)) });
|
|
93
99
|
}
|
|
94
|
-
function KnowTopicFileList({
|
|
100
|
+
function KnowTopicFileList({
|
|
101
|
+
files
|
|
102
|
+
}) {
|
|
95
103
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: files.map((file) => {
|
|
96
104
|
const title = file.display_title ?? file.title ?? file.topic_name ?? "Untitled";
|
|
97
105
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -108,4 +116,4 @@ export {
|
|
|
108
116
|
KnowTopicList,
|
|
109
117
|
KnowTopicFileList
|
|
110
118
|
};
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
119
|
+
//# sourceMappingURL=chunk-3VDQDFHG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/knowledges/knowledges-output.tsx"],"sourcesContent":["import type { CngApi } from \"@cng/client\";\nimport { Box, Text } from \"ink\";\n\nimport { singleLine } from \"../../shared/command-utils.js\";\nimport { formatCatalogPathForDisplay } from \"./knowledges-input.js\";\n\nexport function KnowCatalogSummary({\n catalog,\n}: {\n readonly catalog: CngApi.HarnessCatalogSummary;\n}) {\n return (\n <Box flexDirection=\"column\">\n <Text>\n <Text bold>Catalog: </Text>\n {catalog.name}\n </Text>\n <Text>\n <Text bold>Files: </Text>\n {catalog.files}\n </Text>\n <Text>\n <Text bold>Blobs: </Text>\n {catalog.blobs}\n </Text>\n <Text>\n <Text bold>Database: </Text>\n {catalog.database.engine} ({catalog.database.binding})\n </Text>\n </Box>\n );\n}\n\nexport function KnowAudienceList({\n audiences,\n}: {\n readonly audiences: readonly CngApi.HarnessAudience[];\n}) {\n if (audiences.length === 0) {\n return <Text color=\"yellow\">No audiences available.</Text>;\n }\n\n return (\n <Box flexDirection=\"column\">\n {audiences.map((audience) => (\n <Box flexDirection=\"column\" key={audience.id} marginBottom={1}>\n <Text>\n <Text color=\"cyan\">{audience.id}</Text>\n <Text> - {audience.label}</Text>\n </Text>\n <Text dimColor>{singleLine(audience.help)}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nexport function KnowSearchResults({\n results,\n}: {\n readonly results: readonly CngApi.HarnessSemanticSearchResult[];\n}) {\n return (\n <Box flexDirection=\"column\">\n {results.map((result, index) => (\n <Box flexDirection=\"column\" key={result.id} marginBottom={1}>\n <Text>\n <Text color=\"cyan\">{index + 1}. </Text>\n <Text bold>{result.title}</Text>\n <Text dimColor> ({result.topicName})</Text>\n </Text>\n <Text dimColor>\n score {result.score.toFixed(3)} | {formatCatalogPathForDisplay(result.path)}\n </Text>\n <Text>{singleLine(result.description || result.contentPreview)}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nexport function KnowTopicList({\n topics,\n}: {\n readonly topics: readonly CngApi.HarnessTopicSummary[];\n}) {\n return (\n <Box flexDirection=\"column\">\n {topics.map((topic) => (\n <Box flexDirection=\"column\" key={topic.id} marginBottom={1}>\n <Text>\n <Text color=\"cyan\">{topic.name}</Text>\n <Text dimColor> [{topic.type}]</Text>\n </Text>\n <Text>\n {topic.title} | files {topic.fileCount} | rating {topic.rating}\n </Text>\n <Text dimColor>{singleLine(topic.description)}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nexport function KnowTopicFileList({\n files,\n}: {\n readonly files: readonly CngApi.HarnessTopicAsset[];\n}) {\n return (\n <Box flexDirection=\"column\">\n {files.map((file) => {\n const title = file.display_title ?? file.title ?? file.topic_name ?? \"Untitled\";\n\n return (\n <Box flexDirection=\"column\" key={`${file.path}-${file.sha256}`} marginBottom={1}>\n <Text color=\"cyan\">{formatCatalogPathForDisplay(file.path)}</Text>\n <Text dimColor>{title}</Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCngApiClient
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YIU6G2D3.js";
|
|
4
4
|
|
|
5
5
|
// src/features/knowledges/knowledges-api.ts
|
|
6
6
|
function createKnowledgesApi(options) {
|
|
@@ -64,4 +64,4 @@ function createKnowledgesApi(options) {
|
|
|
64
64
|
export {
|
|
65
65
|
createKnowledgesApi
|
|
66
66
|
};
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
67
|
+
//# sourceMappingURL=chunk-55IPOJ3R.js.map
|
|
@@ -1,13 +1,35 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCngApiClient,
|
|
3
3
|
readBackendHealth
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YIU6G2D3.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveApiBaseUrl
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-X3UQB2CC.js";
|
|
8
8
|
|
|
9
9
|
// src/features/coderoom/run-coderoom-command.ts
|
|
10
10
|
import process3 from "process";
|
|
11
|
+
import { createElement } from "react";
|
|
12
|
+
|
|
13
|
+
// src/features/coderoom/coderoom-output.tsx
|
|
14
|
+
import { Box, Text } from "ink";
|
|
15
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
+
function CoderoomShareCard({
|
|
17
|
+
roomCode,
|
|
18
|
+
command
|
|
19
|
+
}) {
|
|
20
|
+
return /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1, marginY: 1, children: [
|
|
21
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "Share this Coderoom" }),
|
|
22
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
23
|
+
"Room code: ",
|
|
24
|
+
roomCode
|
|
25
|
+
] }),
|
|
26
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
|
|
27
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Send this command to your partner:" }),
|
|
28
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: command })
|
|
29
|
+
] }),
|
|
30
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Keep this terminal running while they join." }) })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
11
33
|
|
|
12
34
|
// src/features/coderoom/sync/client.ts
|
|
13
35
|
import WebSocket2 from "ws";
|
|
@@ -70,7 +92,7 @@ async function shouldSyncRelativePath(context, relativePath) {
|
|
|
70
92
|
return false;
|
|
71
93
|
} catch (error) {
|
|
72
94
|
const exitCode = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
73
|
-
return exitCode
|
|
95
|
+
return exitCode !== 0;
|
|
74
96
|
}
|
|
75
97
|
}
|
|
76
98
|
|
|
@@ -292,6 +314,9 @@ function createSyncWebSocketUrl(options) {
|
|
|
292
314
|
if (options.creatorToken) {
|
|
293
315
|
url.searchParams.set("creatorToken", options.creatorToken);
|
|
294
316
|
}
|
|
317
|
+
if (options.acceptanceToken) {
|
|
318
|
+
url.searchParams.set("acceptanceToken", options.acceptanceToken);
|
|
319
|
+
}
|
|
295
320
|
return url.toString();
|
|
296
321
|
}
|
|
297
322
|
function sendMessage(socket, message) {
|
|
@@ -303,10 +328,12 @@ function createDisplayName() {
|
|
|
303
328
|
const username = os.userInfo().username || "user";
|
|
304
329
|
return `${username}@${os.hostname()}`;
|
|
305
330
|
}
|
|
306
|
-
async function waitForSessionClose(socket, watcher) {
|
|
331
|
+
async function waitForSessionClose(socket, watcher, output) {
|
|
307
332
|
await new Promise((resolve, reject) => {
|
|
308
333
|
let settled = false;
|
|
334
|
+
let shutdownRequested = false;
|
|
309
335
|
const closeSession = async () => {
|
|
336
|
+
output.info("Closing Coderoom session...");
|
|
310
337
|
await watcher.close();
|
|
311
338
|
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
312
339
|
socket.close();
|
|
@@ -320,9 +347,14 @@ async function waitForSessionClose(socket, watcher) {
|
|
|
320
347
|
process.off("SIGINT", onSignal);
|
|
321
348
|
process.off("SIGTERM", onSignal);
|
|
322
349
|
await closeSession();
|
|
350
|
+
if (shutdownRequested) {
|
|
351
|
+
output.success("Coderoom session closed.");
|
|
352
|
+
}
|
|
323
353
|
resolve();
|
|
324
354
|
};
|
|
325
355
|
const onSignal = () => {
|
|
356
|
+
shutdownRequested = true;
|
|
357
|
+
output.warning("Shutdown requested. Closing Coderoom cleanly...");
|
|
326
358
|
void finish();
|
|
327
359
|
};
|
|
328
360
|
socket.on("error", async (error) => {
|
|
@@ -336,6 +368,9 @@ async function waitForSessionClose(socket, watcher) {
|
|
|
336
368
|
reject(error);
|
|
337
369
|
});
|
|
338
370
|
socket.on("close", () => {
|
|
371
|
+
if (!shutdownRequested) {
|
|
372
|
+
output.warning("Coderoom socket closed.");
|
|
373
|
+
}
|
|
339
374
|
void finish();
|
|
340
375
|
});
|
|
341
376
|
process.on("SIGINT", onSignal);
|
|
@@ -378,11 +413,19 @@ function createRepoWatcher(context) {
|
|
|
378
413
|
}
|
|
379
414
|
async function sendInitialSnapshot(socket, repoContext, output) {
|
|
380
415
|
let fileCount = 0;
|
|
416
|
+
let totalBytes = 0;
|
|
417
|
+
output.info("Scanning files for initial Coderoom snapshot...");
|
|
381
418
|
for await (const message of collectSnapshotMessages(repoContext)) {
|
|
419
|
+
if (message.type !== "file") {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const byteCount = Buffer.byteLength(message.contentBase64, "base64");
|
|
423
|
+
totalBytes += byteCount;
|
|
382
424
|
sendMessage(socket, message);
|
|
383
425
|
fileCount += 1;
|
|
426
|
+
output.info(`uploaded snapshot file ${message.path} (${formatByteCount(byteCount)})`);
|
|
384
427
|
}
|
|
385
|
-
output.success(`sent snapshot ${fileCount} files`);
|
|
428
|
+
output.success(`sent snapshot ${fileCount} files (${formatByteCount(totalBytes)})`);
|
|
386
429
|
}
|
|
387
430
|
async function sendLocalFileChange(context, absolutePath) {
|
|
388
431
|
if (!context.state.approved) {
|
|
@@ -393,11 +436,13 @@ async function sendLocalFileChange(context, absolutePath) {
|
|
|
393
436
|
return;
|
|
394
437
|
}
|
|
395
438
|
const message = await buildFileMessage(context.repoContext, relativePath);
|
|
396
|
-
if (!message) {
|
|
439
|
+
if (!message || message.type !== "file") {
|
|
397
440
|
return;
|
|
398
441
|
}
|
|
399
442
|
sendMessage(context.socket, message);
|
|
400
|
-
context.output.
|
|
443
|
+
context.output.info(
|
|
444
|
+
`uploaded file ${relativePath} (${formatByteCount(Buffer.byteLength(message.contentBase64, "base64"))})`
|
|
445
|
+
);
|
|
401
446
|
}
|
|
402
447
|
async function sendLocalDelete(context, absolutePath) {
|
|
403
448
|
if (!context.state.approved) {
|
|
@@ -415,7 +460,17 @@ async function sendLocalDelete(context, absolutePath) {
|
|
|
415
460
|
path: relativePath,
|
|
416
461
|
mtimeMs: Date.now()
|
|
417
462
|
});
|
|
418
|
-
context.output.warning(`
|
|
463
|
+
context.output.warning(`uploaded delete ${relativePath}`);
|
|
464
|
+
}
|
|
465
|
+
function formatByteCount(byteCount) {
|
|
466
|
+
if (byteCount < 1024) {
|
|
467
|
+
return `${byteCount} B`;
|
|
468
|
+
}
|
|
469
|
+
const kibibytes = byteCount / 1024;
|
|
470
|
+
if (kibibytes < 1024) {
|
|
471
|
+
return `${kibibytes.toFixed(1)} KiB`;
|
|
472
|
+
}
|
|
473
|
+
return `${(kibibytes / 1024).toFixed(1)} MiB`;
|
|
419
474
|
}
|
|
420
475
|
|
|
421
476
|
// src/features/coderoom/sync/remote-handler.ts
|
|
@@ -459,8 +514,8 @@ async function handleServerMessage(options) {
|
|
|
459
514
|
return;
|
|
460
515
|
}
|
|
461
516
|
if (decodedMessage.type === "file-ack") {
|
|
462
|
-
options.output.
|
|
463
|
-
`stored ${decodedMessage.storage} ${decodedMessage.path} ${decodedMessage.sha256}`
|
|
517
|
+
options.output.info(
|
|
518
|
+
`stored ${decodedMessage.storage} ${decodedMessage.path} (${formatByteCount2(decodedMessage.size)}) ${decodedMessage.sha256}`
|
|
464
519
|
);
|
|
465
520
|
return;
|
|
466
521
|
}
|
|
@@ -471,6 +526,16 @@ async function handleServerMessage(options) {
|
|
|
471
526
|
await applyRemoteMessage(options.repoContext, decodedMessage, options.suppressionTracker);
|
|
472
527
|
options.output.success(`applied ${decodedMessage.type} ${decodedMessage.path}`);
|
|
473
528
|
}
|
|
529
|
+
function formatByteCount2(byteCount) {
|
|
530
|
+
if (byteCount < 1024) {
|
|
531
|
+
return `${byteCount} B`;
|
|
532
|
+
}
|
|
533
|
+
const kibibytes = byteCount / 1024;
|
|
534
|
+
if (kibibytes < 1024) {
|
|
535
|
+
return `${kibibytes.toFixed(1)} KiB`;
|
|
536
|
+
}
|
|
537
|
+
return `${(kibibytes / 1024).toFixed(1)} MiB`;
|
|
538
|
+
}
|
|
474
539
|
async function approveJoinRequest(socket, message, output) {
|
|
475
540
|
const approved = await askForApproval(message, output);
|
|
476
541
|
sendMessage(socket, {
|
|
@@ -525,6 +590,10 @@ async function startSyncSession(options) {
|
|
|
525
590
|
void sendInitialSnapshot(socket, repoContext, options.output);
|
|
526
591
|
return;
|
|
527
592
|
}
|
|
593
|
+
if (options.acceptanceToken) {
|
|
594
|
+
options.output.info("Using acceptance token. Waiting for room tree...");
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
528
597
|
options.output.info("Waiting for host approval...");
|
|
529
598
|
});
|
|
530
599
|
socket.on("message", (data) => {
|
|
@@ -537,22 +606,23 @@ async function startSyncSession(options) {
|
|
|
537
606
|
output: options.output
|
|
538
607
|
});
|
|
539
608
|
});
|
|
540
|
-
await waitForSessionClose(socket, watcher);
|
|
609
|
+
await waitForSessionClose(socket, watcher, options.output);
|
|
541
610
|
}
|
|
542
611
|
|
|
543
612
|
// src/features/coderoom/run-coderoom-command.ts
|
|
544
613
|
async function runShareCommand(options, output) {
|
|
545
614
|
const room = await createCoderoomRoom(options);
|
|
546
615
|
output.success(`Share code: ${room.roomCode}`);
|
|
616
|
+
printPartnerJoinBox(room, output);
|
|
547
617
|
await printBackendStatus(options, output);
|
|
548
|
-
await runSyncSession("host", room.roomCode, room.creatorToken, options, output);
|
|
618
|
+
await runSyncSession("host", room.roomCode, room.creatorToken, void 0, options, output);
|
|
549
619
|
}
|
|
550
620
|
async function runJoinCommand(roomCode, options, output) {
|
|
551
621
|
if (!roomCode) {
|
|
552
622
|
throw new Error("Missing room code. Usage: cngkit coderoom join <room-code>");
|
|
553
623
|
}
|
|
554
624
|
await printBackendStatus(options, output);
|
|
555
|
-
await runSyncSession("guest", roomCode, void 0, options, output);
|
|
625
|
+
await runSyncSession("guest", roomCode, void 0, options.acceptanceToken, options, output);
|
|
556
626
|
}
|
|
557
627
|
async function printBackendStatus(options, output) {
|
|
558
628
|
const health = await readBackendHealth(options);
|
|
@@ -562,11 +632,12 @@ async function printBackendStatus(options, output) {
|
|
|
562
632
|
}
|
|
563
633
|
output.warning(`API: unavailable (${health.message})`);
|
|
564
634
|
}
|
|
565
|
-
async function runSyncSession(role, roomCode, creatorToken, options, output) {
|
|
635
|
+
async function runSyncSession(role, roomCode, creatorToken, acceptanceToken, options, output) {
|
|
566
636
|
await startSyncSession({
|
|
567
637
|
apiBaseUrl: resolveApiBaseUrl(options),
|
|
568
638
|
roomCode,
|
|
569
639
|
creatorToken,
|
|
640
|
+
acceptanceToken,
|
|
570
641
|
role,
|
|
571
642
|
cwd: process3.cwd(),
|
|
572
643
|
output
|
|
@@ -576,9 +647,14 @@ async function createCoderoomRoom(options) {
|
|
|
576
647
|
const client = createCngApiClient(options);
|
|
577
648
|
return client.coderoom.createCoderoomRoom();
|
|
578
649
|
}
|
|
650
|
+
function printPartnerJoinBox(room, output) {
|
|
651
|
+
const command = `npx --yes cngkit@latest coderoom join ${room.roomCode} --acceptance-token ${room.acceptanceToken}`;
|
|
652
|
+
output.component(createElement(CoderoomShareCard, { roomCode: room.roomCode, command }));
|
|
653
|
+
output.raw(`Copy command: ${command}`);
|
|
654
|
+
}
|
|
579
655
|
|
|
580
656
|
export {
|
|
581
657
|
runShareCommand,
|
|
582
658
|
runJoinCommand
|
|
583
659
|
};
|
|
584
|
-
//# sourceMappingURL=chunk-
|
|
660
|
+
//# sourceMappingURL=chunk-DDQ5TITN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/coderoom/run-coderoom-command.ts","../src/features/coderoom/coderoom-output.tsx","../src/features/coderoom/sync/client.ts","../src/features/coderoom/sync/files.ts","../src/features/coderoom/sync/paths.ts","../src/features/coderoom/sync/local-events.ts","../src/features/coderoom/sync/session.ts","../src/features/coderoom/sync/protocol.ts","../src/features/coderoom/sync/remote-handler.ts"],"sourcesContent":["import process from \"node:process\";\nimport { createElement } from \"react\";\n\nimport { createCngApiClient, readBackendHealth } from \"../../shared/api-client.js\";\nimport { resolveApiBaseUrl, type GlobalCommandOptions } from \"../../shared/config.js\";\nimport type { CommandOutput } from \"../../shared/output/types.js\";\nimport { CoderoomShareCard } from \"./coderoom-output.js\";\nimport { startSyncSession, type SyncSessionRole } from \"./sync/client.js\";\n\nexport type CoderoomCommandOptions = GlobalCommandOptions;\n\nexport type ShareCommandOptions = GlobalCommandOptions;\nexport type JoinCommandOptions = GlobalCommandOptions & {\n readonly acceptanceToken?: string;\n};\n\nexport async function runCoderoomCommand(\n args: string[] | undefined,\n options: CoderoomCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const [subcommand, ...subcommandArgs] = args ?? [];\n\n switch (subcommand) {\n case \"share\":\n return runShareCommand(options, output);\n case \"join\":\n return runJoinCommand(subcommandArgs[0], options, output);\n default:\n throw new Error(\"Missing coderoom command. Usage: cngkit coderoom <share|join>\");\n }\n}\n\nexport async function runShareCommand(\n options: ShareCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const room = await createCoderoomRoom(options);\n\n output.success(`Share code: ${room.roomCode}`);\n printPartnerJoinBox(room, output);\n await printBackendStatus(options, output);\n await runSyncSession(\"host\", room.roomCode, room.creatorToken, undefined, options, output);\n}\n\nexport async function runJoinCommand(\n roomCode: string | undefined,\n options: JoinCommandOptions,\n output: CommandOutput\n): Promise<void> {\n if (!roomCode) {\n throw new Error(\"Missing room code. Usage: cngkit coderoom join <room-code>\");\n }\n\n await printBackendStatus(options, output);\n await runSyncSession(\"guest\", roomCode, undefined, options.acceptanceToken, options, output);\n}\n\nasync function printBackendStatus(\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const health = await readBackendHealth(options);\n if (health.ok) {\n output.success(`API: ${health.service} ready`);\n return;\n }\n\n output.warning(`API: unavailable (${health.message})`);\n}\n\nasync function runSyncSession(\n role: SyncSessionRole,\n roomCode: string,\n creatorToken: string | undefined,\n acceptanceToken: string | undefined,\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n await startSyncSession({\n apiBaseUrl: resolveApiBaseUrl(options),\n roomCode,\n creatorToken,\n acceptanceToken,\n role,\n cwd: process.cwd(),\n output,\n });\n}\n\nasync function createCoderoomRoom(options: GlobalCommandOptions): Promise<{\n roomCode: string;\n creatorToken: string;\n acceptanceToken: string;\n}> {\n const client = createCngApiClient(options);\n return client.coderoom.createCoderoomRoom();\n}\n\nfunction printPartnerJoinBox(\n room: {\n roomCode: string;\n acceptanceToken: string;\n },\n output: CommandOutput\n): void {\n const command = `npx --yes cngkit@latest coderoom join ${room.roomCode} --acceptance-token ${room.acceptanceToken}`;\n output.component(createElement(CoderoomShareCard, { roomCode: room.roomCode, command }));\n output.raw(`Copy command: ${command}`);\n}\n","import { Box, Text } from \"ink\";\n\nexport function CoderoomShareCard({\n roomCode,\n command,\n}: {\n readonly roomCode: string;\n readonly command: string;\n}) {\n return (\n <Box borderStyle=\"round\" borderColor=\"cyan\" flexDirection=\"column\" paddingX={1} marginY={1}>\n <Text bold color=\"cyan\">\n Share this Coderoom\n </Text>\n <Text>Room code: {roomCode}</Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>Send this command to your partner:</Text>\n <Text color=\"green\">{command}</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Keep this terminal running while they join.</Text>\n </Box>\n </Box>\n );\n}\n","// Public API entrypoint for the coderoom sync client. Implementation lives in\n// `./session.ts` (WebSocket lifecycle), `./local-events.ts` (file watcher +\n// outbound events), and `./remote-handler.ts` (inbound message dispatch).\n\nimport WebSocket from \"ws\";\n\nimport { createSuppressionTracker } from \"./files.js\";\nimport { createRepoWatcher, sendInitialSnapshot, type WatcherContext } from \"./local-events.js\";\nimport { resolveRepoContext } from \"./paths.js\";\nimport { handleServerMessage } from \"./remote-handler.js\";\nimport { createSyncWebSocketUrl, waitForSessionClose } from \"./session.js\";\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\n\nexport type SyncSessionRole = \"host\" | \"guest\";\n\nexport type StartSyncSessionOptions = {\n apiBaseUrl: string;\n roomCode: string;\n creatorToken?: string;\n acceptanceToken?: string;\n role: SyncSessionRole;\n cwd: string;\n output: CommandOutput;\n};\n\nexport async function startSyncSession(options: StartSyncSessionOptions): Promise<void> {\n const repoContext = await resolveRepoContext(options.cwd);\n const suppressionTracker = createSuppressionTracker();\n const webSocketUrl = createSyncWebSocketUrl(options);\n const socket = new WebSocket(webSocketUrl);\n const state = {\n approved: options.role === \"host\",\n participantId: undefined as string | undefined,\n };\n\n options.output.success(`Room: ${options.roomCode}`);\n options.output.info(`Repo: ${repoContext.rootDir}`);\n\n const watcherContext: WatcherContext = {\n repoContext,\n socket,\n state,\n suppressionTracker,\n output: options.output,\n };\n const watcher = createRepoWatcher(watcherContext);\n\n socket.on(\"open\", () => {\n if (options.role === \"host\") {\n void sendInitialSnapshot(socket, repoContext, options.output);\n return;\n }\n\n if (options.acceptanceToken) {\n options.output.info(\"Using acceptance token. Waiting for room tree...\");\n return;\n }\n\n options.output.info(\"Waiting for host approval...\");\n });\n\n socket.on(\"message\", (data) => {\n void handleServerMessage({\n data,\n socket,\n repoContext,\n state,\n suppressionTracker,\n output: options.output,\n });\n });\n\n await waitForSessionClose(socket, watcher, options.output);\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { ClientMessage, ServerFileMutationMessage } from \"./protocol.js\";\nimport {\n resolveRepoPath,\n shouldSyncRelativePath,\n toRepoRelativePath,\n type RepoContext,\n} from \"./paths.js\";\n\nexport type SuppressionTracker = {\n suppress(relativePath: string): void;\n isSuppressed(relativePath: string): boolean;\n};\n\nexport function createSuppressionTracker(windowMs = 1500): SuppressionTracker {\n const suppressedUntilByPath = new Map<string, number>();\n\n return {\n suppress(relativePath: string) {\n suppressedUntilByPath.set(relativePath, Date.now() + windowMs);\n },\n isSuppressed(relativePath: string) {\n const suppressedUntil = suppressedUntilByPath.get(relativePath);\n if (!suppressedUntil) {\n return false;\n }\n if (suppressedUntil < Date.now()) {\n suppressedUntilByPath.delete(relativePath);\n return false;\n }\n return true;\n },\n };\n}\n\nexport async function* collectSnapshotMessages(\n context: RepoContext\n): AsyncGenerator<ClientMessage> {\n yield* collectDirectorySnapshot(context, context.rootDir);\n}\n\nasync function* collectDirectorySnapshot(\n context: RepoContext,\n directoryPath: string\n): AsyncGenerator<ClientMessage> {\n const entries = await fs.opendir(directoryPath);\n\n for await (const entry of entries) {\n const absolutePath = path.join(directoryPath, entry.name);\n const relativePath = toRepoRelativePath(context.rootDir, absolutePath);\n\n if (!relativePath || !(await shouldSyncRelativePath(context, relativePath))) {\n continue;\n }\n\n if (entry.isDirectory()) {\n yield* collectDirectorySnapshot(context, absolutePath);\n continue;\n }\n\n if (!entry.isFile()) {\n continue;\n }\n\n const [content, stat] = await Promise.all([fs.readFile(absolutePath), fs.stat(absolutePath)]);\n yield {\n type: \"file\",\n path: relativePath,\n contentBase64: content.toString(\"base64\"),\n mtimeMs: stat.mtimeMs,\n };\n }\n}\n\nexport async function buildFileMessage(\n context: RepoContext,\n relativePath: string\n): Promise<ClientMessage | undefined> {\n if (!(await shouldSyncRelativePath(context, relativePath))) {\n return undefined;\n }\n\n const absolutePath = resolveRepoPath(context.rootDir, relativePath);\n if (!absolutePath) {\n return undefined;\n }\n\n const stat = await fs.stat(absolutePath);\n if (!stat.isFile()) {\n return undefined;\n }\n\n const content = await fs.readFile(absolutePath);\n return {\n type: \"file\",\n path: relativePath,\n contentBase64: content.toString(\"base64\"),\n mtimeMs: stat.mtimeMs,\n };\n}\n\nexport async function applyRemoteMessage(\n context: RepoContext,\n message: ServerFileMutationMessage,\n suppressionTracker: SuppressionTracker\n): Promise<void> {\n const absolutePath = resolveRepoPath(context.rootDir, message.path);\n if (!absolutePath || !(await shouldSyncRelativePath(context, message.path))) {\n return;\n }\n\n suppressionTracker.suppress(message.path);\n\n if (message.type === \"delete\") {\n await fs.rm(absolutePath, { force: true });\n return;\n }\n\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await fs.writeFile(absolutePath, Buffer.from(message.contentBase64, \"base64\"));\n}\n","import { execFile } from \"node:child_process\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type RepoContext = {\n rootDir: string;\n};\n\nexport async function resolveRepoContext(cwd: string): Promise<RepoContext> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n });\n return { rootDir: path.resolve(stdout.trim()) };\n } catch {\n return { rootDir: path.resolve(cwd) };\n }\n}\n\nexport function toRepoRelativePath(rootDir: string, absolutePath: string): string | undefined {\n const relativePath = path.relative(rootDir, absolutePath);\n\n if (!relativePath || relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n return undefined;\n }\n\n return relativePath.split(path.sep).join(\"/\");\n}\n\nexport function resolveRepoPath(rootDir: string, relativePath: string): string | undefined {\n if (!isSafeRelativePath(relativePath)) {\n return undefined;\n }\n\n const absolutePath = path.resolve(rootDir, relativePath);\n const normalizedRoot = `${path.resolve(rootDir)}${path.sep}`;\n\n if (absolutePath !== path.resolve(rootDir) && !absolutePath.startsWith(normalizedRoot)) {\n return undefined;\n }\n\n return absolutePath;\n}\n\nexport function isSafeRelativePath(relativePath: string): boolean {\n if (!relativePath || relativePath.startsWith(\"/\") || relativePath.includes(\"\\0\")) {\n return false;\n }\n\n const normalizedParts = relativePath.split(/[\\\\/]+/).filter(Boolean);\n if (normalizedParts.includes(\"..\")) {\n return false;\n }\n\n return normalizedParts[0] !== \".git\";\n}\n\nexport async function shouldSyncRelativePath(\n context: RepoContext,\n relativePath: string\n): Promise<boolean> {\n if (!isSafeRelativePath(relativePath)) {\n return false;\n }\n\n try {\n await execFileAsync(\"git\", [\"check-ignore\", \"--quiet\", \"--\", relativePath], {\n cwd: context.rootDir,\n });\n return false;\n } catch (error) {\n const exitCode =\n typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n return exitCode !== 0;\n }\n}\n","import fs from \"node:fs\";\n\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport WebSocket from \"ws\";\n\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\nimport { buildFileMessage, collectSnapshotMessages, type SuppressionTracker } from \"./files.js\";\nimport { shouldSyncRelativePath, toRepoRelativePath, type RepoContext } from \"./paths.js\";\nimport { sendMessage } from \"./session.js\";\n\ntype SessionState = {\n approved: boolean;\n participantId?: string;\n};\n\nexport type WatcherContext = {\n repoContext: RepoContext;\n socket: WebSocket;\n state: SessionState;\n suppressionTracker: SuppressionTracker;\n output: CommandOutput;\n};\n\nexport function createRepoWatcher(context: WatcherContext): FSWatcher {\n const watcher = chokidar.watch(context.repoContext.rootDir, {\n ignoreInitial: true,\n ignored: (candidatePath) => {\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, candidatePath);\n if (relativePath?.split(\"/\").includes(\".git\") ?? false) {\n return true;\n }\n try {\n const stat = fs.statSync(candidatePath);\n return !stat.isFile() && !stat.isDirectory();\n } catch {\n return false;\n }\n },\n });\n\n watcher.on(\"add\", (absolutePath) => {\n void sendLocalFileChange(context, absolutePath);\n });\n watcher.on(\"change\", (absolutePath) => {\n void sendLocalFileChange(context, absolutePath);\n });\n watcher.on(\"unlink\", (absolutePath) => {\n void sendLocalDelete(context, absolutePath);\n });\n watcher.on(\"error\", (watcherError) => {\n context.output.warning(\n `watcher error: ${watcherError instanceof Error ? watcherError.message : String(watcherError)}`\n );\n });\n\n return watcher;\n}\n\nexport async function sendInitialSnapshot(\n socket: WebSocket,\n repoContext: RepoContext,\n output: CommandOutput\n): Promise<void> {\n let fileCount = 0;\n let totalBytes = 0;\n\n output.info(\"Scanning files for initial Coderoom snapshot...\");\n for await (const message of collectSnapshotMessages(repoContext)) {\n if (message.type !== \"file\") {\n continue;\n }\n\n const byteCount = Buffer.byteLength(message.contentBase64, \"base64\");\n totalBytes += byteCount;\n sendMessage(socket, message);\n fileCount += 1;\n output.info(`uploaded snapshot file ${message.path} (${formatByteCount(byteCount)})`);\n }\n\n output.success(`sent snapshot ${fileCount} files (${formatByteCount(totalBytes)})`);\n}\n\nasync function sendLocalFileChange(context: WatcherContext, absolutePath: string): Promise<void> {\n if (!context.state.approved) {\n return;\n }\n\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, absolutePath);\n if (!relativePath || context.suppressionTracker.isSuppressed(relativePath)) {\n return;\n }\n\n const message = await buildFileMessage(context.repoContext, relativePath);\n if (!message || message.type !== \"file\") {\n return;\n }\n\n sendMessage(context.socket, message);\n context.output.info(\n `uploaded file ${relativePath} (${formatByteCount(Buffer.byteLength(message.contentBase64, \"base64\"))})`\n );\n}\n\nasync function sendLocalDelete(context: WatcherContext, absolutePath: string): Promise<void> {\n if (!context.state.approved) {\n return;\n }\n\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, absolutePath);\n if (!relativePath || context.suppressionTracker.isSuppressed(relativePath)) {\n return;\n }\n\n if (!(await shouldSyncRelativePath(context.repoContext, relativePath))) {\n return;\n }\n\n sendMessage(context.socket, {\n type: \"delete\",\n path: relativePath,\n mtimeMs: Date.now(),\n });\n context.output.warning(`uploaded delete ${relativePath}`);\n}\n\nfunction formatByteCount(byteCount: number): string {\n if (byteCount < 1024) {\n return `${byteCount} B`;\n }\n\n const kibibytes = byteCount / 1024;\n if (kibibytes < 1024) {\n return `${kibibytes.toFixed(1)} KiB`;\n }\n\n return `${(kibibytes / 1024).toFixed(1)} MiB`;\n}\n","import os from \"node:os\";\nimport process from \"node:process\";\n\nimport { type FSWatcher } from \"chokidar\";\nimport WebSocket from \"ws\";\n\nimport { encodeClientMessage, type ClientMessage } from \"./protocol.js\";\nimport type { StartSyncSessionOptions } from \"./client.js\";\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\n\nexport function createSyncWebSocketUrl(options: StartSyncSessionOptions): string {\n const url = new URL(options.apiBaseUrl);\n url.protocol = url.protocol === \"http:\" ? \"ws:\" : \"wss:\";\n url.pathname = `/api/cng/coderoom/rooms/${encodeURIComponent(options.roomCode)}/ws`;\n url.search = \"\";\n url.hash = \"\";\n url.searchParams.set(\"role\", options.role);\n url.searchParams.set(\"displayName\", createDisplayName());\n if (options.creatorToken) {\n url.searchParams.set(\"creatorToken\", options.creatorToken);\n }\n if (options.acceptanceToken) {\n url.searchParams.set(\"acceptanceToken\", options.acceptanceToken);\n }\n return url.toString();\n}\n\nexport function sendMessage(socket: WebSocket, message: ClientMessage): void {\n if (socket.readyState === WebSocket.OPEN) {\n socket.send(encodeClientMessage(message));\n }\n}\n\nexport function createDisplayName(): string {\n const username = os.userInfo().username || \"user\";\n return `${username}@${os.hostname()}`;\n}\n\nexport async function waitForSessionClose(\n socket: WebSocket,\n watcher: FSWatcher,\n output: CommandOutput\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n let shutdownRequested = false;\n\n const closeSession = async (): Promise<void> => {\n output.info(\"Closing Coderoom session...\");\n await watcher.close();\n if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {\n socket.close();\n }\n };\n\n const finish = async (): Promise<void> => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await closeSession();\n if (shutdownRequested) {\n output.success(\"Coderoom session closed.\");\n }\n resolve();\n };\n\n const onSignal = (): void => {\n shutdownRequested = true;\n output.warning(\"Shutdown requested. Closing Coderoom cleanly...\");\n void finish();\n };\n\n socket.on(\"error\", async (error) => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await closeSession();\n reject(error);\n });\n\n socket.on(\"close\", () => {\n if (!shutdownRequested) {\n output.warning(\"Coderoom socket closed.\");\n }\n void finish();\n });\n\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n });\n}\n","import { z } from \"zod\";\n\nexport const ClientFileMessageSchema = z.object({\n type: z.literal(\"file\"),\n path: z.string().min(1),\n contentBase64: z.string(),\n mtimeMs: z.number().finite(),\n});\n\nexport const ClientDeleteMessageSchema = z.object({\n type: z.literal(\"delete\"),\n path: z.string().min(1),\n mtimeMs: z.number().finite(),\n});\n\nexport const ClientJoinApprovalMessageSchema = z.object({\n type: z.literal(\"join-approval\"),\n joinRequestId: z.string().min(1),\n approved: z.boolean(),\n});\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n ClientFileMessageSchema,\n ClientDeleteMessageSchema,\n ClientJoinApprovalMessageSchema,\n]);\n\nexport const ServerConnectedMessageSchema = z.object({\n type: z.literal(\"connected\"),\n roomCode: z.string(),\n participantId: z.string(),\n role: z.union([z.literal(\"host\"), z.literal(\"guest\")]),\n status: z.union([z.literal(\"approved\"), z.literal(\"pending\"), z.literal(\"denied\")]),\n});\n\nexport const ServerJoinPendingMessageSchema = z.object({\n type: z.literal(\"join-pending\"),\n participantId: z.string(),\n joinRequestId: z.string(),\n roomCode: z.string(),\n});\n\nexport const ServerJoinRequestMessageSchema = z.object({\n type: z.literal(\"join-request\"),\n joinRequestId: z.string(),\n participantId: z.string(),\n displayName: z.string(),\n requestedAt: z.number().finite(),\n});\n\nexport const ServerJoinApprovedMessageSchema = z.object({\n type: z.literal(\"join-approved\"),\n participantId: z.string(),\n});\n\nexport const ServerJoinDeniedMessageSchema = z.object({\n type: z.literal(\"join-denied\"),\n participantId: z.string(),\n reason: z.string(),\n});\n\nexport const ServerFileMessageSchema = z.object({\n type: z.literal(\"file\"),\n fileId: z.string(),\n path: z.string().min(1),\n sha256: z.string(),\n size: z.number().int().nonnegative(),\n contentBase64: z.string(),\n mtimeMs: z.number().finite(),\n updatedByParticipantId: z.string(),\n});\n\nexport const ServerDeleteMessageSchema = z.object({\n type: z.literal(\"delete\"),\n fileId: z.string().optional(),\n path: z.string().min(1),\n mtimeMs: z.number().finite(),\n updatedByParticipantId: z.string(),\n});\n\nexport const ServerFileAckMessageSchema = z.object({\n type: z.literal(\"file-ack\"),\n fileId: z.string(),\n path: z.string().min(1),\n sha256: z.string(),\n size: z.number().int().nonnegative(),\n storage: z.union([z.literal(\"durable-object\"), z.literal(\"r2\")]),\n});\n\nexport const ServerTreeStartMessageSchema = z.object({\n type: z.literal(\"tree-start\"),\n fileCount: z.number().int().nonnegative(),\n});\n\nexport const ServerTreeCompleteMessageSchema = z.object({\n type: z.literal(\"tree-complete\"),\n fileCount: z.number().int().nonnegative(),\n});\n\nexport const ServerErrorMessageSchema = z.object({\n type: z.literal(\"error\"),\n error: z.string(),\n});\n\nexport const ServerMessageSchema = z.discriminatedUnion(\"type\", [\n ServerConnectedMessageSchema,\n ServerJoinPendingMessageSchema,\n ServerJoinRequestMessageSchema,\n ServerJoinApprovedMessageSchema,\n ServerJoinDeniedMessageSchema,\n ServerFileMessageSchema,\n ServerDeleteMessageSchema,\n ServerFileAckMessageSchema,\n ServerTreeStartMessageSchema,\n ServerTreeCompleteMessageSchema,\n ServerErrorMessageSchema,\n]);\n\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\nexport type ServerFileMutationMessage = Extract<ServerMessage, { type: \"file\" | \"delete\" }>;\n\nexport function encodeClientMessage(message: ClientMessage): string {\n return JSON.stringify(ClientMessageSchema.parse(message));\n}\n\nexport function decodeServerMessage(value: unknown): ServerMessage | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n try {\n return ServerMessageSchema.parse(JSON.parse(value));\n } catch {\n return undefined;\n }\n}\n","import process from \"node:process\";\nimport readline from \"node:readline/promises\";\n\nimport WebSocket, { type RawData } from \"ws\";\n\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\nimport { applyRemoteMessage, type SuppressionTracker } from \"./files.js\";\nimport type { RepoContext } from \"./paths.js\";\nimport { decodeServerMessage, type ServerMessage } from \"./protocol.js\";\nimport { sendMessage } from \"./session.js\";\n\ntype SessionState = {\n approved: boolean;\n participantId?: string;\n};\n\nexport type HandleServerMessageOptions = {\n data: RawData;\n socket: WebSocket;\n repoContext: RepoContext;\n state: SessionState;\n suppressionTracker: SuppressionTracker;\n output: CommandOutput;\n};\n\nexport async function handleServerMessage(options: HandleServerMessageOptions): Promise<void> {\n const decodedMessage = decodeServerMessage(options.data.toString());\n if (!decodedMessage) {\n return;\n }\n\n if (decodedMessage.type === \"connected\") {\n options.state.participantId = decodedMessage.participantId;\n options.state.approved = decodedMessage.status === \"approved\";\n options.output.muted(`Participant: ${decodedMessage.participantId}`);\n return;\n }\n\n if (decodedMessage.type === \"join-pending\") {\n options.output.info(`Join request sent: ${decodedMessage.joinRequestId}`);\n return;\n }\n\n if (decodedMessage.type === \"join-request\") {\n await approveJoinRequest(options.socket, decodedMessage, options.output);\n return;\n }\n\n if (decodedMessage.type === \"join-approved\") {\n options.state.approved = true;\n options.output.success(\"Join approved. Applying room file tree...\");\n return;\n }\n\n if (decodedMessage.type === \"join-denied\") {\n options.output.warning(`Join denied: ${decodedMessage.reason}`);\n options.socket.close();\n return;\n }\n\n if (decodedMessage.type === \"tree-start\") {\n options.output.info(`receiving room tree ${decodedMessage.fileCount} files`);\n return;\n }\n\n if (decodedMessage.type === \"tree-complete\") {\n options.output.success(`room tree complete ${decodedMessage.fileCount} files`);\n return;\n }\n\n if (decodedMessage.type === \"file-ack\") {\n options.output.info(\n `stored ${decodedMessage.storage} ${decodedMessage.path} (${formatByteCount(decodedMessage.size)}) ${decodedMessage.sha256}`\n );\n return;\n }\n\n if (decodedMessage.type === \"error\") {\n options.output.warning(`server error: ${decodedMessage.error}`);\n return;\n }\n\n await applyRemoteMessage(options.repoContext, decodedMessage, options.suppressionTracker);\n options.output.success(`applied ${decodedMessage.type} ${decodedMessage.path}`);\n}\n\nfunction formatByteCount(byteCount: number): string {\n if (byteCount < 1024) {\n return `${byteCount} B`;\n }\n\n const kibibytes = byteCount / 1024;\n if (kibibytes < 1024) {\n return `${kibibytes.toFixed(1)} KiB`;\n }\n\n return `${(kibibytes / 1024).toFixed(1)} MiB`;\n}\n\nasync function approveJoinRequest(\n socket: WebSocket,\n message: Extract<ServerMessage, { type: \"join-request\" }>,\n output: CommandOutput\n): Promise<void> {\n const approved = await askForApproval(message, output);\n sendMessage(socket, {\n type: \"join-approval\",\n joinRequestId: message.joinRequestId,\n approved,\n });\n output[approved ? \"success\" : \"warning\"](\n `${approved ? \"approved\" : \"denied\"} ${message.displayName}`\n );\n}\n\nasync function askForApproval(\n message: Extract<ServerMessage, { type: \"join-request\" }>,\n output: CommandOutput\n): Promise<boolean> {\n output.info(`Join request: ${message.displayName} (${message.joinRequestId})`);\n if (!process.stdin.isTTY) {\n output.warning(\"No interactive terminal available. Denying join request.\");\n return false;\n }\n\n const interfaceReader = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n try {\n const answer = await interfaceReader.question(\"Approve join request? [y/N] \");\n return answer.trim().toLowerCase() === \"y\" || answer.trim().toLowerCase() === \"yes\";\n } finally {\n interfaceReader.close();\n }\n}\n"],"mappings":"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","names":["process","WebSocket","path","path","fs","fs","process","formatByteCount","process","WebSocket","process"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/knowledges/format/content-format.ts"],"sourcesContent":["import type { CngApi } from \"@cng/client\";\n\nimport {\n formatJson,\n shouldPrintJson,\n type JsonOutputOptions,\n} from \"../../../shared/command-utils.js\";\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\n\nexport function outputRawContent(\n data: CngApi.HarnessReadResponse,\n options: JsonOutputOptions,\n output: CommandOutput\n): void {\n if (shouldPrintJson(options)) {\n output.raw(formatJson(data));\n return;\n }\n\n output.raw(data.content);\n}\n"],"mappings":";;;;;;AASO,SAAS,iBACd,MACA,SACA,QACM;AACN,MAAI,gBAAgB,OAAO,GAAG;AAC5B,WAAO,IAAI,WAAW,IAAI,CAAC;AAC3B;AAAA,EACF;AAEA,SAAO,IAAI,KAAK,OAAO;AACzB;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
formatCatalogPathForDisplay
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2Y5FMKFS.js";
|
|
4
4
|
import {
|
|
5
5
|
coerceOptionalNumber
|
|
6
6
|
} from "./chunk-XQGLUQFM.js";
|
|
@@ -99,4 +99,4 @@ export {
|
|
|
99
99
|
coerceOptionalFiniteNumber,
|
|
100
100
|
formatFilesystemStat
|
|
101
101
|
};
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
102
|
+
//# sourceMappingURL=chunk-LNFZT3R3.js.map
|
|
@@ -482,7 +482,7 @@ var helpTopicDocuments = [
|
|
|
482
482
|
language: "bash",
|
|
483
483
|
lines: [
|
|
484
484
|
"npx --yes cngkit@latest coderoom share",
|
|
485
|
-
"npx --yes cngkit@latest coderoom join <room-code>"
|
|
485
|
+
"npx --yes cngkit@latest coderoom join <room-code> --acceptance-token <token>"
|
|
486
486
|
]
|
|
487
487
|
},
|
|
488
488
|
{
|
|
@@ -494,8 +494,9 @@ var helpTopicDocuments = [
|
|
|
494
494
|
items: [
|
|
495
495
|
"Creates rooms through `/api/cng/coderoom/rooms` and connects to `/api/cng/coderoom/rooms/:roomCode/ws` on the configured backend.",
|
|
496
496
|
"Uses WebSocket transport backed by the `CoderoomRoom` Durable Object.",
|
|
497
|
-
"The server creates room codes, creator tokens, participant IDs, join request IDs, and file IDs.",
|
|
498
|
-
"
|
|
497
|
+
"The server creates room codes, creator tokens, guest acceptance tokens, participant IDs, join request IDs, and file IDs.",
|
|
498
|
+
"The share command prints a copy-ready partner command with an acceptance token.",
|
|
499
|
+
"Joiners with the acceptance token are approved automatically; joiners without it wait in a lobby until the host approves them.",
|
|
499
500
|
"The Durable Object stores the room file tree with hashes; large file bodies are stored in R2.",
|
|
500
501
|
"The host sends an initial snapshot, then approved participants send file and delete events.",
|
|
501
502
|
"Last received change wins.",
|
|
@@ -531,8 +532,9 @@ var helpTopicDocuments = [
|
|
|
531
532
|
items: [
|
|
532
533
|
"Creates the room through `/api/cng/coderoom/rooms`, then connects to `/api/cng/coderoom/rooms/:roomCode/ws`.",
|
|
533
534
|
"Uses WebSocket transport backed by the `CoderoomRoom` Durable Object.",
|
|
534
|
-
"Prints the server-created share code.",
|
|
535
|
-
"
|
|
535
|
+
"Prints the server-created share code and an Ink share card with a copy-ready partner command.",
|
|
536
|
+
"The partner command includes a guest acceptance token so the partner can join without a separate approval prompt.",
|
|
537
|
+
"Prompts the host to approve or deny join requests that do not include the acceptance token.",
|
|
536
538
|
"Sends an initial snapshot, then file and delete events after the room is open.",
|
|
537
539
|
"Last received change wins."
|
|
538
540
|
]
|
|
@@ -557,7 +559,7 @@ var helpTopicDocuments = [
|
|
|
557
559
|
{
|
|
558
560
|
kind: "list",
|
|
559
561
|
items: [
|
|
560
|
-
"Prints room code, repo root, server-assigned participant id, backend health, join requests, and
|
|
562
|
+
"Prints room code, a copy-ready partner command, repo root, server-assigned participant id, backend health, join requests, upload events, storage acknowledgements, and shutdown status.",
|
|
561
563
|
"Keeps running until the socket closes or the process receives a termination signal."
|
|
562
564
|
]
|
|
563
565
|
}
|
|
@@ -579,7 +581,10 @@ var helpTopicDocuments = [
|
|
|
579
581
|
{
|
|
580
582
|
kind: "code",
|
|
581
583
|
language: "bash",
|
|
582
|
-
lines: [
|
|
584
|
+
lines: [
|
|
585
|
+
"cngkit coderoom join <room-code>",
|
|
586
|
+
"cngkit coderoom join <room-code> --acceptance-token <token>"
|
|
587
|
+
]
|
|
583
588
|
},
|
|
584
589
|
{
|
|
585
590
|
kind: "section",
|
|
@@ -587,7 +592,7 @@ var helpTopicDocuments = [
|
|
|
587
592
|
},
|
|
588
593
|
{
|
|
589
594
|
kind: "paragraph",
|
|
590
|
-
text: "Same transport and filesystem contract as `cngkit coderoom share`. The supplied room code selects the Durable Object room,
|
|
595
|
+
text: "Same transport and filesystem contract as `cngkit coderoom share`. The supplied room code selects the Durable Object room. If the host's share command included an acceptance token, the joiner is approved automatically; otherwise the joiner waits until the host approves access."
|
|
591
596
|
},
|
|
592
597
|
{
|
|
593
598
|
kind: "section",
|
|
@@ -1593,4 +1598,4 @@ export {
|
|
|
1593
1598
|
renderCngkitHelp,
|
|
1594
1599
|
renderKnowledgesHelp
|
|
1595
1600
|
};
|
|
1596
|
-
//# sourceMappingURL=chunk-
|
|
1601
|
+
//# sourceMappingURL=chunk-QCAHQE7Q.js.map
|