contextgit 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/bin/run.js +4 -0
  2. package/dist/bootstrap.d.ts +10 -0
  3. package/dist/bootstrap.d.ts.map +1 -0
  4. package/dist/bootstrap.js +43 -0
  5. package/dist/bootstrap.js.map +1 -0
  6. package/dist/commands/branch.d.ts +13 -0
  7. package/dist/commands/branch.d.ts.map +1 -0
  8. package/dist/commands/branch.js +52 -0
  9. package/dist/commands/branch.js.map +1 -0
  10. package/dist/commands/claim.d.ts +13 -0
  11. package/dist/commands/claim.d.ts.map +1 -0
  12. package/dist/commands/claim.js +50 -0
  13. package/dist/commands/claim.js.map +1 -0
  14. package/dist/commands/commit.d.ts +14 -0
  15. package/dist/commands/commit.d.ts.map +1 -0
  16. package/dist/commands/commit.js +71 -0
  17. package/dist/commands/commit.js.map +1 -0
  18. package/dist/commands/context.d.ts +9 -0
  19. package/dist/commands/context.d.ts.map +1 -0
  20. package/dist/commands/context.js +38 -0
  21. package/dist/commands/context.js.map +1 -0
  22. package/dist/commands/doctor.d.ts +6 -0
  23. package/dist/commands/doctor.d.ts.map +1 -0
  24. package/dist/commands/doctor.js +84 -0
  25. package/dist/commands/doctor.js.map +1 -0
  26. package/dist/commands/init.d.ts +10 -0
  27. package/dist/commands/init.d.ts.map +1 -0
  28. package/dist/commands/init.js +126 -0
  29. package/dist/commands/init.js.map +1 -0
  30. package/dist/commands/keygen.d.ts +10 -0
  31. package/dist/commands/keygen.d.ts.map +1 -0
  32. package/dist/commands/keygen.js +57 -0
  33. package/dist/commands/keygen.js.map +1 -0
  34. package/dist/commands/log.d.ts +13 -0
  35. package/dist/commands/log.d.ts.map +1 -0
  36. package/dist/commands/log.js +91 -0
  37. package/dist/commands/log.js.map +1 -0
  38. package/dist/commands/merge.d.ts +12 -0
  39. package/dist/commands/merge.d.ts.map +1 -0
  40. package/dist/commands/merge.js +29 -0
  41. package/dist/commands/merge.js.map +1 -0
  42. package/dist/commands/pull.d.ts +10 -0
  43. package/dist/commands/pull.d.ts.map +1 -0
  44. package/dist/commands/pull.js +123 -0
  45. package/dist/commands/pull.js.map +1 -0
  46. package/dist/commands/push.d.ts +10 -0
  47. package/dist/commands/push.d.ts.map +1 -0
  48. package/dist/commands/push.js +141 -0
  49. package/dist/commands/push.js.map +1 -0
  50. package/dist/commands/remote-show.d.ts +6 -0
  51. package/dist/commands/remote-show.d.ts.map +1 -0
  52. package/dist/commands/remote-show.js +71 -0
  53. package/dist/commands/remote-show.js.map +1 -0
  54. package/dist/commands/search.d.ts +11 -0
  55. package/dist/commands/search.d.ts.map +1 -0
  56. package/dist/commands/search.js +47 -0
  57. package/dist/commands/search.js.map +1 -0
  58. package/dist/commands/serve.d.ts +9 -0
  59. package/dist/commands/serve.d.ts.map +1 -0
  60. package/dist/commands/serve.js +51 -0
  61. package/dist/commands/serve.js.map +1 -0
  62. package/dist/commands/set-remote.d.ts +9 -0
  63. package/dist/commands/set-remote.d.ts.map +1 -0
  64. package/dist/commands/set-remote.js +26 -0
  65. package/dist/commands/set-remote.js.map +1 -0
  66. package/dist/commands/status.d.ts +6 -0
  67. package/dist/commands/status.d.ts.map +1 -0
  68. package/dist/commands/status.js +54 -0
  69. package/dist/commands/status.js.map +1 -0
  70. package/dist/commands/unclaim.d.ts +9 -0
  71. package/dist/commands/unclaim.d.ts.map +1 -0
  72. package/dist/commands/unclaim.js +22 -0
  73. package/dist/commands/unclaim.js.map +1 -0
  74. package/dist/config.d.ts +19 -0
  75. package/dist/config.d.ts.map +1 -0
  76. package/dist/config.js +58 -0
  77. package/dist/config.js.map +1 -0
  78. package/dist/git-hooks.d.ts +6 -0
  79. package/dist/git-hooks.d.ts.map +1 -0
  80. package/dist/git-hooks.js +58 -0
  81. package/dist/git-hooks.js.map +1 -0
  82. package/package.json +27 -9
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class KeygenCmd extends Command {
3
+ static description: string;
4
+ static flags: {
5
+ save: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
6
+ length: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=keygen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keygen.d.ts","sourceRoot":"","sources":["../../src/commands/keygen.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAwB5C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAC,WAAW,SAA+D;IAEjF,MAAM,CAAC,KAAK;;;MASX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAiB3B"}
@@ -0,0 +1,57 @@
1
+ // keygen — generate an API key and optionally save its hash to ~/.contextgit/server.json.
2
+ //
3
+ // The plaintext key is shown once and never written to disk. Only the SHA-256
4
+ // hash is persisted so the server can verify Bearer tokens without storing secrets.
5
+ import os from 'os';
6
+ import { join } from 'path';
7
+ import { createHash } from 'crypto';
8
+ import { mkdirSync, readFileSync, writeFileSync } from 'fs';
9
+ import { Command, Flags } from '@oclif/core';
10
+ import { nanoid } from 'nanoid';
11
+ const CONTEXTGIT_DIR = join(os.homedir(), '.contextgit');
12
+ const SERVER_CONFIG_PATH = join(CONTEXTGIT_DIR, 'server.json');
13
+ function sha256hex(input) {
14
+ return createHash('sha256').update(input, 'utf8').digest('hex');
15
+ }
16
+ function readServerConfig() {
17
+ try {
18
+ return JSON.parse(readFileSync(SERVER_CONFIG_PATH, 'utf-8'));
19
+ }
20
+ catch {
21
+ return {};
22
+ }
23
+ }
24
+ function saveKeyHash(hash) {
25
+ mkdirSync(CONTEXTGIT_DIR, { recursive: true });
26
+ const cfg = { ...readServerConfig(), keyHash: hash };
27
+ writeFileSync(SERVER_CONFIG_PATH, JSON.stringify(cfg, null, 2) + '\n', { mode: 0o600 });
28
+ }
29
+ export default class KeygenCmd extends Command {
30
+ static description = 'Generate an API key for securing the ContextGit API server';
31
+ static flags = {
32
+ save: Flags.boolean({
33
+ description: 'Save the key hash to ~/.contextgit/server.json (key shown once, never stored)',
34
+ default: false,
35
+ }),
36
+ length: Flags.integer({
37
+ description: 'Key length (default 32)',
38
+ default: 32,
39
+ }),
40
+ };
41
+ async run() {
42
+ const { flags } = await this.parse(KeygenCmd);
43
+ const key = nanoid(flags.length);
44
+ this.log(`API Key: ${key}`);
45
+ this.log(`(Copy this now — it will not be stored anywhere in plaintext)`);
46
+ if (flags.save) {
47
+ saveKeyHash(sha256hex(key));
48
+ this.log(`\nKey hash saved to ~/.contextgit/server.json`);
49
+ this.log(`Set this key in the Authorization header when calling the API:`);
50
+ this.log(` Authorization: Bearer ${key}`);
51
+ }
52
+ else {
53
+ this.log(`\nTo activate this key, re-run with --save`);
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=keygen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keygen.js","sourceRoot":"","sources":["../../src/commands/keygen.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,EAAE;AACF,8EAA8E;AAC9E,oFAAoF;AAEpF,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAA;AACxD,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAA;AAE9D,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjE,CAAC;AAED,SAAS,gBAAgB;IACvB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAA4B,CAAA;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,MAAM,GAAG,GAAG,EAAE,GAAG,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IACpD,aAAa,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AACzF,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAC,WAAW,GAAG,4DAA4D,CAAA;IAEjF,MAAM,CAAC,KAAK,GAAG;QACb,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YAClB,WAAW,EAAE,+EAA+E;YAC5F,OAAO,EAAE,KAAK;SACf,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC;YACpB,WAAW,EAAE,yBAAyB;YACtC,OAAO,EAAE,EAAE;SACZ,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAE7C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAEhC,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,EAAE,CAAC,CAAA;QAC3B,IAAI,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAA;QAEzE,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;YAC3B,IAAI,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAA;YACzD,IAAI,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAA;YAC1E,IAAI,CAAC,GAAG,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAA;QAC5C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAA;QACxD,CAAC;IACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class LogCmd extends Command {
3
+ static description: string;
4
+ static flags: {
5
+ limit: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
+ all: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
7
+ branch: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ verbose: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ private printCommits;
12
+ }
13
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAK5C,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IACzC,MAAM,CAAC,WAAW,SAAgD;IAElE,MAAM,CAAC,KAAK;;;;;MAoBX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAgD1B,OAAO,CAAC,YAAY;CAsBrB"}
@@ -0,0 +1,91 @@
1
+ // log — list context commits with formatting.
2
+ import { Command, Flags } from '@oclif/core';
3
+ import { simpleGit } from 'simple-git';
4
+ import { LocalStore } from '@contextgit/store';
5
+ import { loadConfig } from '../config.js';
6
+ export default class LogCmd extends Command {
7
+ static description = 'List context commits for the current branch';
8
+ static flags = {
9
+ limit: Flags.integer({
10
+ char: 'n',
11
+ description: 'Max commits to show',
12
+ default: 20,
13
+ }),
14
+ all: Flags.boolean({
15
+ char: 'a',
16
+ description: 'Show commits across all branches',
17
+ default: false,
18
+ }),
19
+ branch: Flags.string({
20
+ char: 'b',
21
+ description: 'Show commits for a specific git branch name',
22
+ }),
23
+ verbose: Flags.boolean({
24
+ char: 'v',
25
+ description: 'Show full commit content',
26
+ default: false,
27
+ }),
28
+ };
29
+ async run() {
30
+ const { flags } = await this.parse(LogCmd);
31
+ const config = loadConfig();
32
+ const store = new LocalStore(config.projectId);
33
+ const cwd = process.cwd();
34
+ let gitBranch = 'main';
35
+ try {
36
+ gitBranch = (await simpleGit(cwd).revparse(['--abbrev-ref', 'HEAD'])).trim();
37
+ }
38
+ catch {
39
+ // fallback
40
+ }
41
+ if (flags.all) {
42
+ const branches = await store.listBranches(config.projectId);
43
+ if (branches.length === 0) {
44
+ this.log('No branches found. Run `contextgit init` first.');
45
+ return;
46
+ }
47
+ for (const branch of branches) {
48
+ const commits = await store.listCommits(branch.id, { limit: flags.limit, offset: 0 });
49
+ if (commits.length === 0)
50
+ continue;
51
+ this.log(`\n── ${branch.name} (${branch.gitBranch}) ──`);
52
+ this.printCommits(commits, flags.verbose);
53
+ }
54
+ }
55
+ else {
56
+ const targetGitBranch = flags.branch ?? gitBranch;
57
+ const branch = await store.getBranchByGitName(config.projectId, targetGitBranch);
58
+ if (!branch) {
59
+ this.error(`No context branch for git branch '${targetGitBranch}'. Run 'contextgit init' first.`);
60
+ }
61
+ const commits = await store.listCommits(branch.id, { limit: flags.limit, offset: 0 });
62
+ if (commits.length === 0) {
63
+ this.log(`No commits on branch '${branch.name}'.`);
64
+ return;
65
+ }
66
+ this.log(`Branch: ${branch.name} [${branch.gitBranch}]`);
67
+ this.log(`Showing ${commits.length} commit(s)\n`);
68
+ this.printCommits(commits, flags.verbose);
69
+ }
70
+ }
71
+ printCommits(commits, verbose) {
72
+ for (const c of commits) {
73
+ const ts = new Date(c.createdAt).toLocaleString();
74
+ const sha = c.gitCommitSha ? ` git:${c.gitCommitSha.slice(0, 7)}` : '';
75
+ const agent = c.agentId ? ` [${c.agentId}]` : '';
76
+ this.log(`commit ${c.id}`);
77
+ this.log(`Date: ${ts}${sha}${agent}`);
78
+ this.log(``);
79
+ this.log(` ${c.message}`);
80
+ if (verbose && c.content && c.content !== c.message) {
81
+ this.log(``);
82
+ const lines = c.content.split('\n');
83
+ for (const line of lines) {
84
+ this.log(` ${line}`);
85
+ }
86
+ }
87
+ this.log(``);
88
+ }
89
+ }
90
+ }
91
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class MergeCmd extends Command {
3
+ static description: string;
4
+ static args: {
5
+ sourceBranchId: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ summary: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/commands/merge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAA;AAGlD,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,MAAM,CAAC,WAAW,SAAmD;IAErE,MAAM,CAAC,IAAI;;MAKV;IAED,MAAM,CAAC,KAAK;;MAMX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAY3B"}
@@ -0,0 +1,29 @@
1
+ // merge — merge a context branch into the current branch.
2
+ import { Command, Args, Flags } from '@oclif/core';
3
+ import { bootstrap } from '../bootstrap.js';
4
+ export default class MergeCmd extends Command {
5
+ static description = 'Merge a context branch into the current branch';
6
+ static args = {
7
+ sourceBranchId: Args.string({
8
+ description: 'ID of the source branch to merge from',
9
+ required: true,
10
+ }),
11
+ };
12
+ static flags = {
13
+ summary: Flags.string({
14
+ char: 's',
15
+ description: 'Summary of what was merged (defaults to a generic message)',
16
+ required: false,
17
+ }),
18
+ };
19
+ async run() {
20
+ const { args, flags } = await this.parse(MergeCmd);
21
+ const ctx = await bootstrap();
22
+ const summary = flags.summary ?? `Merged branch ${args.sourceBranchId} into current branch`;
23
+ const mergeCommit = await ctx.store.mergeBranch(args.sourceBranchId, ctx.branchId, summary);
24
+ this.log(`Branch merged.`);
25
+ this.log(`Merge commit ID: ${mergeCommit.id}`);
26
+ this.log(`Summary: ${mergeCommit.summary}`);
27
+ }
28
+ }
29
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/commands/merge.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,MAAM,CAAC,WAAW,GAAG,gDAAgD,CAAA;IAErE,MAAM,CAAC,IAAI,GAAG;QACZ,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC;YAC1B,WAAW,EAAE,uCAAuC;YACpD,QAAQ,EAAE,IAAI;SACf,CAAC;KACH,CAAA;IAED,MAAM,CAAC,KAAK,GAAG;QACb,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC;YACpB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,4DAA4D;YACzE,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAClD,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAA;QAE7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,iBAAiB,IAAI,CAAC,cAAc,sBAAsB,CAAA;QAE3F,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAE3F,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC1B,IAAI,CAAC,GAAG,CAAC,oBAAoB,WAAW,CAAC,EAAE,EAAE,CAAC,CAAA;QAC9C,IAAI,CAAC,GAAG,CAAC,YAAY,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;IAC7C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class PullCmd extends Command {
3
+ static description: string;
4
+ static flags: {
5
+ remote: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
+ 'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAwB5C,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAAsD;IAExE,MAAM,CAAC,KAAK;;;MAUX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAiG3B"}
@@ -0,0 +1,123 @@
1
+ // pull — pull context commits from a remote ContextGit API server into local store.
2
+ //
3
+ // Requires `remote` in .contextgit/config.json.
4
+ // Algorithm:
5
+ // 1. Ensure project exists locally (by ID — already initialized)
6
+ // 2. For each remote branch: ensure branch exists locally
7
+ // 3. For each branch: collect remote commits not present locally, write them
8
+ import { Command, Flags } from '@oclif/core';
9
+ import { LocalStore, RemoteStore } from '@contextgit/store';
10
+ import { loadConfig } from '../config.js';
11
+ const PAGE = 100;
12
+ async function allCommits(store, branchId) {
13
+ const acc = [];
14
+ let offset = 0;
15
+ const pg = { limit: PAGE, offset };
16
+ while (true) {
17
+ pg.offset = offset;
18
+ const page = await store.listCommits(branchId, pg);
19
+ acc.push(...page);
20
+ if (page.length < PAGE)
21
+ break;
22
+ offset += PAGE;
23
+ }
24
+ return acc;
25
+ }
26
+ export default class PullCmd extends Command {
27
+ static description = 'Pull context commits from a remote ContextGit API';
28
+ static flags = {
29
+ remote: Flags.string({
30
+ char: 'r',
31
+ description: 'Remote API URL (overrides config.remote)',
32
+ required: false,
33
+ }),
34
+ 'dry-run': Flags.boolean({
35
+ description: 'Show what would be pulled without writing locally',
36
+ default: false,
37
+ }),
38
+ };
39
+ async run() {
40
+ const { flags } = await this.parse(PullCmd);
41
+ const config = loadConfig();
42
+ const remoteUrl = flags.remote ?? config.remote;
43
+ if (!remoteUrl) {
44
+ this.error('No remote configured. Add "remote": "<url>" to .contextgit/config.json or pass --remote.');
45
+ }
46
+ const local = new LocalStore(config.projectId);
47
+ const remote = new RemoteStore(remoteUrl);
48
+ const dryRun = flags['dry-run'];
49
+ // Verify project exists on remote
50
+ const remoteProject = await remote.getProject(config.projectId).catch(() => null);
51
+ if (!remoteProject) {
52
+ this.error(`Project ${config.projectId} not found on remote ${remoteUrl}. Push first.`);
53
+ }
54
+ // List all remote branches
55
+ const remoteBranches = await remote.listBranches(config.projectId);
56
+ let totalPulled = 0;
57
+ for (const branch of remoteBranches) {
58
+ // Ensure branch exists locally
59
+ const localBranch = await local.getBranch(branch.id).catch(() => null);
60
+ if (!localBranch) {
61
+ if (!dryRun) {
62
+ await local.createBranch({
63
+ id: branch.id,
64
+ projectId: branch.projectId,
65
+ name: branch.name,
66
+ gitBranch: branch.gitBranch,
67
+ parentBranchId: branch.parentBranchId,
68
+ });
69
+ }
70
+ this.log(`[branch] ${dryRun ? 'would create' : 'created'}: ${branch.name}`);
71
+ }
72
+ // Collect local commit IDs for this branch
73
+ const localCommits = await allCommits(local, branch.id);
74
+ const localCommitIds = new Set(localCommits.map(c => c.id));
75
+ // Pull missing commits from remote
76
+ const remoteCommits = await allCommits(remote, branch.id);
77
+ const missing = remoteCommits.filter(c => !localCommitIds.has(c.id));
78
+ if (missing.length === 0) {
79
+ this.log(`[branch] ${branch.name}: up to date (${remoteCommits.length} commits)`);
80
+ continue;
81
+ }
82
+ this.log(`[branch] ${branch.name}: pulling ${missing.length} commit(s)…`);
83
+ for (const commit of missing) {
84
+ if (!dryRun) {
85
+ await local.createCommit({
86
+ id: commit.id,
87
+ branchId: commit.branchId,
88
+ parentId: commit.parentId,
89
+ agentId: commit.agentId,
90
+ agentRole: commit.agentRole,
91
+ tool: commit.tool,
92
+ workflowType: commit.workflowType,
93
+ loopIteration: commit.loopIteration,
94
+ ciRunId: commit.ciRunId,
95
+ pipelineName: commit.pipelineName,
96
+ message: commit.message,
97
+ content: commit.content,
98
+ summary: commit.summary,
99
+ commitType: commit.commitType,
100
+ gitCommitSha: commit.gitCommitSha,
101
+ });
102
+ }
103
+ totalPulled++;
104
+ }
105
+ }
106
+ // Thread sync: pull open threads that are missing locally
107
+ const remoteThreads = await remote.listOpenThreads(config.projectId);
108
+ const localThreads = await local.listOpenThreads(config.projectId);
109
+ const localThreadIds = new Set(localThreads.map(t => t.id));
110
+ const missingThreads = remoteThreads.filter(t => !localThreadIds.has(t.id));
111
+ if (missingThreads.length > 0) {
112
+ this.log(`\n[threads] pulling ${missingThreads.length} open thread(s)…`);
113
+ for (const thread of missingThreads) {
114
+ if (!dryRun) {
115
+ await local.syncThread(thread);
116
+ }
117
+ this.log(` ${dryRun ? 'would pull' : 'pulled'}: ${thread.description}`);
118
+ }
119
+ }
120
+ this.log(`\nDone. ${dryRun ? '(dry run) ' : ''}${totalPulled} commit(s), ${missingThreads.length} thread(s) pulled from ${remoteUrl}`);
121
+ }
122
+ }
123
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class PushCmd extends Command {
3
+ static description: string;
4
+ static flags: {
5
+ remote: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
+ 'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAwB5C,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAA0D;IAE5E,MAAM,CAAC,KAAK;;;MAUX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA8G3B"}
@@ -0,0 +1,141 @@
1
+ // push — push local context commits to a remote ContextGit API server.
2
+ //
3
+ // Requires `remote` in .contextgit/config.json.
4
+ // Algorithm:
5
+ // 1. Ensure project exists on remote (idempotent via ID)
6
+ // 2. For each local branch: ensure branch exists on remote
7
+ // 3. For each branch: collect local commits not present on remote, POST them
8
+ import { Command, Flags } from '@oclif/core';
9
+ import { LocalStore, RemoteStore } from '@contextgit/store';
10
+ import { loadConfig } from '../config.js';
11
+ const PAGE = 100;
12
+ async function allCommits(store, branchId) {
13
+ const acc = [];
14
+ let offset = 0;
15
+ const pg = { limit: PAGE, offset };
16
+ while (true) {
17
+ pg.offset = offset;
18
+ const page = await store.listCommits(branchId, pg);
19
+ acc.push(...page);
20
+ if (page.length < PAGE)
21
+ break;
22
+ offset += PAGE;
23
+ }
24
+ return acc;
25
+ }
26
+ export default class PushCmd extends Command {
27
+ static description = 'Push local context commits to a remote ContextGit API';
28
+ static flags = {
29
+ remote: Flags.string({
30
+ char: 'r',
31
+ description: 'Remote API URL (overrides config.remote)',
32
+ required: false,
33
+ }),
34
+ 'dry-run': Flags.boolean({
35
+ description: 'Show what would be pushed without actually pushing',
36
+ default: false,
37
+ }),
38
+ };
39
+ async run() {
40
+ const { flags } = await this.parse(PushCmd);
41
+ const config = loadConfig();
42
+ const remoteUrl = flags.remote ?? config.remote;
43
+ if (!remoteUrl) {
44
+ this.error('No remote configured. Use: contextgit set-remote <url>', { exit: 1 });
45
+ }
46
+ const local = new LocalStore(config.projectId);
47
+ const remote = new RemoteStore(remoteUrl);
48
+ const dryRun = flags['dry-run'];
49
+ // 1. Ensure project on remote
50
+ const existingProject = await remote.getProject(config.projectId).catch(() => null);
51
+ if (!existingProject) {
52
+ if (!dryRun) {
53
+ await remote.createProject({ id: config.projectId, name: config.project });
54
+ }
55
+ this.log(`[project] ${dryRun ? 'would create' : 'created'}: ${config.project}`);
56
+ }
57
+ else {
58
+ this.log(`[project] already exists: ${config.project}`);
59
+ }
60
+ // 2. List all local branches
61
+ const branches = await local.listBranches(config.projectId);
62
+ let totalPushed = 0;
63
+ for (const branch of branches) {
64
+ // Ensure branch on remote
65
+ const remoteBranch = await remote.getBranch(branch.id).catch(() => null);
66
+ if (!remoteBranch) {
67
+ if (!dryRun) {
68
+ await remote.createBranch({
69
+ id: branch.id,
70
+ projectId: branch.projectId,
71
+ name: branch.name,
72
+ gitBranch: branch.gitBranch,
73
+ parentBranchId: branch.parentBranchId,
74
+ });
75
+ }
76
+ this.log(`[branch] ${dryRun ? 'would create' : 'created'}: ${branch.name}`);
77
+ }
78
+ // Collect remote commit IDs for this branch
79
+ let remoteCommitIds;
80
+ try {
81
+ const remoteCommits = await allCommits(remote, branch.id);
82
+ remoteCommitIds = new Set(remoteCommits.map(c => c.id));
83
+ }
84
+ catch {
85
+ remoteCommitIds = new Set();
86
+ }
87
+ // Push missing commits
88
+ const localCommits = await allCommits(local, branch.id);
89
+ const missing = localCommits.filter(c => !remoteCommitIds.has(c.id));
90
+ if (missing.length === 0) {
91
+ this.log(`[branch] ${branch.name}: up to date (${localCommits.length} commits)`);
92
+ continue;
93
+ }
94
+ this.log(`[branch] ${branch.name}: pushing ${missing.length} commit(s)…`);
95
+ for (const commit of missing) {
96
+ if (!dryRun) {
97
+ await remote.createCommit({
98
+ id: commit.id,
99
+ branchId: commit.branchId,
100
+ parentId: commit.parentId,
101
+ agentId: commit.agentId,
102
+ agentRole: commit.agentRole,
103
+ tool: commit.tool,
104
+ workflowType: commit.workflowType,
105
+ loopIteration: commit.loopIteration,
106
+ ciRunId: commit.ciRunId,
107
+ pipelineName: commit.pipelineName,
108
+ message: commit.message,
109
+ content: commit.content,
110
+ summary: commit.summary,
111
+ commitType: commit.commitType,
112
+ gitCommitSha: commit.gitCommitSha,
113
+ });
114
+ }
115
+ totalPushed++;
116
+ }
117
+ }
118
+ // Thread sync: push open threads that are missing on remote
119
+ const localThreads = await local.listOpenThreads(config.projectId);
120
+ let remoteThreadIds;
121
+ try {
122
+ const remoteThreads = await remote.listOpenThreads(config.projectId);
123
+ remoteThreadIds = new Set(remoteThreads.map(t => t.id));
124
+ }
125
+ catch {
126
+ remoteThreadIds = new Set();
127
+ }
128
+ const missingThreads = localThreads.filter(t => !remoteThreadIds.has(t.id));
129
+ if (missingThreads.length > 0) {
130
+ this.log(`\n[threads] pushing ${missingThreads.length} open thread(s)…`);
131
+ for (const thread of missingThreads) {
132
+ if (!dryRun) {
133
+ await remote.syncThread(thread);
134
+ }
135
+ this.log(` ${dryRun ? 'would push' : 'pushed'}: ${thread.description}`);
136
+ }
137
+ }
138
+ this.log(`\nDone. ${dryRun ? '(dry run) ' : ''}${totalPushed} commit(s), ${missingThreads.length} thread(s) pushed to ${remoteUrl}`);
139
+ }
140
+ }
141
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class RemoteShowCmd extends Command {
3
+ static description: string;
4
+ run(): Promise<void>;
5
+ }
6
+ //# sourceMappingURL=remote-show.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-show.d.ts","sourceRoot":"","sources":["../../src/commands/remote-show.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AA0BrC,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,OAAO;IAChD,MAAM,CAAC,WAAW,SAAoD;IAEhE,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuD3B"}