Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ client.receive().takeWhile { env ->
when (val p = env.payload) {
is JobStatusEvent -> { println("status: ${p.phase} ${p.body}"); true }
is JobProgress -> { println("progress: ${p.percent}% ${p.message}"); true }
is Metric -> { println("metric: ${p.name}=${p.value} ${p.unit ?: ""}"); true }
is Metric -> { println("metric: ${p.name}=${p.value} ${p.unit}"); true }
is JobResultChunk -> { chunks.accept(p); true }
is JobCompleted -> { println("result: ${p.result}"); false }
is JobFailed -> { println("failed: ${p.code} ${p.message}"); false }
Expand Down Expand Up @@ -222,7 +222,7 @@ try {
client.receive().collect { env ->
val m = env.payload as? Metric ?: return@collect
if (m.name == StandardMetrics.COST_BUDGET_REMAINING) {
println("budget remaining: ${m.value} ${m.unit ?: ""}")
println("budget remaining: ${m.value} ${m.unit}")
}
}
} catch (e: ARCPException.BudgetExhausted) {
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/job-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ progress, heartbeat, chunk, and status events.
Sent when the agent begins executing:

```kotlin
is JobStarted -> println("Job ${msg.jobId} is now running")
is JobStarted -> println("Job ${env.jobId} is now running")
```

## JobProgress
Expand Down
7 changes: 6 additions & 1 deletion lib/src/main/kotlin/dev/arcp/client/ResultChunkAssembler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import dev.arcp.messages.ResultChunkEncoding
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi

/** Client-side accumulator for `result_chunk` streams (RFC v1.1 §8.4). */
/**
* Client-side accumulator for `result_chunk` streams (RFC v1.1 §8.4).
*
* Not thread-safe: use one assembler per result stream and call [accept]
* from a single coroutine.
*/
public class ResultChunkAssembler(
private val maxAssembledSize: Long = DEFAULT_MAX_ASSEMBLED_SIZE,
) {
Expand Down
4 changes: 3 additions & 1 deletion lib/src/main/kotlin/dev/arcp/messages/Session.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public enum class HeartbeatRecovery {
/**
* Negotiated capability set (RFC §7).
*
* Absent boolean fields default to `false` per §7. The `extensions` list
* Absent boolean fields default to `false` per §7, except `interrupt`,
* which defaults to `true` for SDK ergonomics. The `extensions` list
* advertises the namespaces accepted on this session (RFC §21.2).
*/
@Serializable
Expand All @@ -47,6 +48,7 @@ public data class Capabilities(
@SerialName("model.use")
val modelUse: Boolean = false,
val anonymous: Boolean = false,
/** Deliberately defaults to `true` for pause-and-ask ergonomics. */
val interrupt: Boolean = true,
@SerialName("heartbeat_interval_seconds")
val heartbeatIntervalSeconds: Int = DEFAULT_HEARTBEAT_INTERVAL_SECONDS,
Expand Down
17 changes: 17 additions & 0 deletions lib/src/test/kotlin/dev/arcp/runtime/CapabilityNegotiationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.arcp.runtime

import dev.arcp.messages.Capabilities
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe

class CapabilityNegotiationTest :
StringSpec({
"interrupt stays enabled when both peers use defaults" {
val proposed = Capabilities()
val supported = Capabilities()

val result = negotiate(proposed, supported)

result.negotiated.interrupt shouldBe true
}
})
Loading