typeclaw 0.1.6 → 0.2.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typeclaw",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "homepage": "https://github.com/typeclaw/typeclaw#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/typeclaw/typeclaw/issues"
@@ -1,6 +1,8 @@
1
1
  import { readFileSync, writeFileSync } from 'node:fs'
2
2
  import { join } from 'node:path'
3
3
 
4
+ import { commitSystemFileSync } from '@/git/system-commit'
5
+
4
6
  import { configSchema, loadConfigSync, validateConfig } from './config'
5
7
  import {
6
8
  KNOWN_PROVIDERS,
@@ -87,7 +89,9 @@ export function setProfile(
87
89
  }
88
90
  }
89
91
 
90
- return writeProfile(cwd, trimmed, ref)
92
+ const existingBefore = readModelsRaw(cwd)
93
+ const verb = existingBefore !== null && trimmed in existingBefore ? 'set' : 'add'
94
+ return writeProfile(cwd, trimmed, ref, `model: ${verb} ${trimmed} → ${ref}`)
91
95
  }
92
96
 
93
97
  // `add` is just `set` with a uniqueness guard; users who want "update" should
@@ -130,19 +134,19 @@ export function removeProfile(cwd: string, profile: string): ModelMutationResult
130
134
  }
131
135
  const next = { ...existing }
132
136
  delete next[profile]
133
- return writeModels(cwd, next)
137
+ return writeModels(cwd, next, `model: remove ${profile}`)
134
138
  }
135
139
 
136
- function writeProfile(cwd: string, profile: string, ref: KnownModelRef): ModelMutationResult {
140
+ function writeProfile(cwd: string, profile: string, ref: KnownModelRef, message: string): ModelMutationResult {
137
141
  const existing = readModelsRaw(cwd)
138
142
  const next = existing === null ? { default: ref } : { ...existing, [profile]: ref }
139
143
  if (existing === null && profile !== 'default') {
140
144
  next.default = ref
141
145
  }
142
- return writeModels(cwd, next)
146
+ return writeModels(cwd, next, message)
143
147
  }
144
148
 
145
- function writeModels(cwd: string, models: Record<string, string>): ModelMutationResult {
149
+ function writeModels(cwd: string, models: Record<string, string>, commitMessage: string): ModelMutationResult {
146
150
  const path = join(cwd, CONFIG_FILE)
147
151
  let parsed: Record<string, unknown>
148
152
  try {
@@ -176,6 +180,11 @@ function writeModels(cwd: string, models: Record<string, string>): ModelMutation
176
180
  if (!validation.ok) {
177
181
  return { ok: false, reason: validation.reason }
178
182
  }
183
+ // Auto-commit so the agent folder is never silently dirty after a CLI
184
+ // config mutation. Same pattern as `persistMigratedConfig` and cron
185
+ // migrations: `commitSystemFileSync` no-ops on non-git folders, missing
186
+ // Bun, and clean files, so callers outside a git repo pay zero cost.
187
+ commitSystemFileSync(cwd, CONFIG_FILE, commitMessage)
179
188
  return { ok: true }
180
189
  }
181
190
 
package/src/init/index.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  type KnownProviderId,
13
13
  } from '@/config/providers'
14
14
  import { checkDockerAvailable, type DockerAvailability, type DockerExec, start } from '@/container'
15
+ import { commitSystemFile } from '@/git/system-commit'
15
16
  import { createSecretsStoreForAgent, type Channels, type Secret, SecretsBackend } from '@/secrets'
16
17
  import { createTui } from '@/tui'
17
18
 
@@ -860,6 +861,13 @@ export async function runAddChannel(options: AddChannelOptions): Promise<void> {
860
861
  await appendChannelSecrets(options.cwd, options.channel, tokens)
861
862
  }
862
863
  emit({ step: 'secrets', phase: 'done' })
864
+
865
+ // Commit the typeclaw.json change so the agent folder isn't silently
866
+ // dirty after `typeclaw channel add`. Same `commitSystemFile` contract as
867
+ // every other host-side rewrite: no-op outside a git repo, when Bun is
868
+ // unavailable, or when the file is clean. secrets.json is gitignored, so
869
+ // only typeclaw.json is named here.
870
+ await commitSystemFile(options.cwd, CONFIG_FILE, `channel: add ${options.channel}`)
863
871
  }
864
872
 
865
873
  function channelSecretsFromOptions(options: AddChannelOptions): ChannelSecrets {